Merge remote-tracking branch 'origin/fara' into roman

This commit is contained in:
3lswear
2022-02-19 22:31:32 +03:00
29 changed files with 690 additions and 265 deletions

View File

@@ -2,9 +2,9 @@ NAME = webserv
CXX = clang++ CXX = clang++
SANFLAGS = -fsanitize=address # SANFLAGS = -fsanitize=address
# SANFLAGS = -fsanitize=leak SANFLAGS = -fsanitize=leak
DEBUGFLAGS = -g -fno-limit-debug-info DEBUGFLAGS = -g -fno-limit-debug-info

View File

@@ -1,18 +1,18 @@
[[server]] [[server]]
name = "pohek1.org" name = "pohek1.org"
host = "127.0.0.1" host = "127.0.0.1" # check inet_addr()
port = 8080 port = 8080 # check num, (0, 65536)
body_size_limit = 10000000 body_size_limit = 10000000 #(pofig and > 0)
[server.error_page] [server.error_page]
403 = "www/errorFolder/index2.html" "404" = "www/errorFolder/error_404.html" # throw exception if not string
[[server.location]] [[server.location]]
location = "/" location = "/" # mandatory
root = "www/" root = "www/" # check valid
methods = ["GET", "POST", "DELETE"] methods = ["GET", "POST", "DELETE"]
autoindex = true autoindex = true #check if bool
directory_file = "index.html" directory_file = "index.html"
upload_accept = true upload_accept = true #throw exception if not bool
upload_dir = "/var/www/html/upload" upload_dir = "www/upload" # check valid
[[server.location]] [[server.location]]
location = "/images" location = "/images"
root = "www/images" root = "www/images"
@@ -20,7 +20,7 @@
autoindex = true autoindex = true
[[server.location]] [[server.location]]
location = "/images/168.png" location = "/images/168.png"
redirect = ["301", "http://127.0.0.1:8080/168.png"] redirect = ["301", "http://127.0.0.1:8080/168.png"] #throw exception if no array, or more 2 elem, or elem is not str
[[server.location]] [[server.location]]
location = "/errorFolder/images/168.png" location = "/errorFolder/images/168.png"
redirect = ["301", "http://127.0.0.1:8080/168.png"] redirect = ["301", "http://127.0.0.1:8080/168.png"]
@@ -32,20 +32,16 @@
location = "*.png" location = "*.png"
root = "www/images/pngImg" root = "www/images/pngImg"
methods = ["GET"] methods = ["GET"]
[[server.location]]
location = "*.ico"
root = "www/images/icoImg"
methods = ["GET"]
[[server.location]] [[server.location]]
location = "/errorFolder" location = "/errorFolder"
root = "www/errorFolder" root = "www/errorFolder"
methods = ["GET", "POST"] methods = ["GET", "POST"]
autoindex = false autoindex = true
[[server.location]] [[server.location]]
location = "*.php" location = "*.php"
root = "www/script" root = "www/script"
autoindex = false autoindex = false
cgi_pass = "/usr/bin/php-cgi" cgi_pass = "/usr/bin/php-cgi" #check valid
[[server]] [[server]]
name = "pohek2.org" name = "pohek2.org"
host = "127.0.0.1" host = "127.0.0.1"
@@ -63,7 +59,7 @@
autoindex = true autoindex = true
directory_file = "index.html" directory_file = "index.html"
upload_accept = false upload_accept = false
upload_dir = "/var/www/html/upload" upload_dir = "www/upload"
[[server]] [[server]]
name = "localhost" name = "localhost"
host = "127.0.0.1" host = "127.0.0.1"
@@ -81,4 +77,4 @@
autoindex = true autoindex = true
directory_file = "index.html" directory_file = "index.html"
upload_accept = false upload_accept = false
upload_dir = "/var/www/html/upload" upload_dir = "www/upload"

View File

@@ -2,28 +2,29 @@
name = "pohek1.org" name = "pohek1.org"
host = "127.0.0.1" host = "127.0.0.1"
port = 8080 port = 8080
body_size_limit = 100000000
[[server.location]] [[server.location]]
location = "/" location = "/"
root = "www/tester/" root = "tester/"
methods = ["GET"] methods = ["GET"]
autoindex = true autoindex = true
directory_file = "index.html" directory_file = "index.html"
[[server.location]] [[server.location]]
location = "/put_test" location = "/put_test"
root = "www/tester/" root = "tester/"
methods = ["PUT"] methods = ["PUT"]
autoindex = true autoindex = true
upload_dir = "www/tester/upload_here/" upload_dir = "tester/upload_here/"
[[server.location]] [[server.location]]
location = "*.bla" location = "*.bla"
cgi_pass = "/usr/bin/php-cgi" cgi_pass = "ubuntu_cgi_tester"
[[server.location]] [[server.location]]
location = "/post_body" location = "/post_body"
root = "www/tester/" root = "tester/"
methods = ["POST"] methods = ["POST"]
body_size_limit = 100 body_size_limit = 100
[[server.location]] [[server.location]]
location = "/directory" location = "/directory"
methods = ["GET"] methods = ["GET"]
root = "www/tester/YoupiBanane/" root = "tester/YoupiBanane/"
directory_file = "youpi.bad_extension" directory_file = "youpi.bad_extension"

View File

@@ -30,6 +30,8 @@
#include <sys/time.h> #include <sys/time.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <wait.h> #include <wait.h>
#include <exception>
#include <csignal>
#include <netinet/in.h> #include <netinet/in.h>
#include <fcntl.h> #include <fcntl.h>

164
second/index.html Normal file
View File

@@ -0,0 +1,164 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8" />
<title>Название сайта</title>
</head>
<body>
<!--Создаём таблицу контейнер, которой задаём следующее
оформление:
border="1" - рамка вокруг контейнера. Увеличив число, можно увеличить толщину рамки.
align="center" - размещаем контейнер по центру экрана.
rules="rows" - убираем двойную рамку.
style="width:60%;" - добавляем стилевое свойства, делающее
контейнер и весь сайт "резиновым".
Сделать полноценный адаптивный дизайн, этим способом невозможно.-->
<table
border="1"
align="center"
rules="rows"
style="width:60%;">
<!--Создаём строку-->
<tr>
<!--Создаём ячейку строки-->
<td>
<!--ШАПКА САЙТА-->
<!--В ячейке строки создаём ещё одну таблицу для шапки сайта.
Оформление:
border="1" - двойная рамка толщиной в 1px
background="images/168.png" - картинка в шапке сайта, если требуется.
Адрес картинки вы должны вставить свой.
bgcolor="#7FFFD4" - фоновый цвет в шапке, если нет картинки.
cellpadding="10" - отступ содержимого от рамки не менее 10px.
style="width:100%; border-radius:5px;" - добавляем "резиновость"
и закругляем уголки рамки-->
<table
border="1"
background="images/168.png"
bgcolor="#7FFFD4"
cellpadding="10"
style="width:100%; border-radius:5px;">
<!--Создаём строку таблицы-->
<tr>
<!--Создаём столбец таблицы-->
<th>
<!--Содержание ячейки столбца-->
<h1>Название сайта (организации)</h1>
<h3>Описание сайта</h3>
<!--Закрываем таблицу-->
</th>
</tr>
</table>
<!--ОСНОВНОЙ КОНТЕНТ-->
<!--В этой же ячейке контейнера создаём ещё одну таблицу
для основного контента.
Оформление как и в предыдущей таблице-->
<table
border="1"
bgcolor="#e6e6fa"
cellpadding="10"
style="width:100%; border-radius:5px;">
<!--Создаём строку-->
<tr>
<!--Создаём ячейку
Оформление:
rowspan="2" - объединяем две ячейки в одну.
Число объединяемых ячеек по числу ячеек в сайдбаре.
style="width:80%" - основной контент занимает 80% всей площади,
оставшиеся 20% для сайдбара-->
<td
rowspan="2"
style="width:80%">
<h2>Страница</h2>
<!--Начинаем абзац с красной строки-->
<p style="text-indent:20px">
Здравствуйте уважаемые будущие веб-мастера!
Мне 55 лет и я рад приветствовать Вас на своём сайте.
Этот сайт первый, который я разработал самостоятельно,
а до этого умел только входить в интернет.</p>
<p style="text-indent:20px">Почему я решил его сделать?
За те 3 месяца, пока разбирался в
сайтостроении и создавал этот ресурс обнаружилось,
что авторы руководств по созданию
сайтов считают многие нюансы само собой разумеющимися
и не обращают на них внимание
А мне, учитывая возраст и «опыт», было не просто
понять как раз эти нюансы, они отнимали больше всего
времени.</p>
<!--Закрываем ячейку-->
</td>
<!--САЙДБАР-->
<!--Создаём ячейку сайдбара-->
<td bgcolor="#e6e6fa">
<h3>Меню</h3>
<!--Абзац для ссылки на страницу сайта-->
<p>
<!--Ссылка на страницу сайта-->
<a href="">
<!--Картинка маркера перед названием страницы-->
<img src="http://trueimages.ru/img/00/06/f4fffdb5.png">
<!--Название страницы
style="margin-left:5px;" - отступ названия от маркера-->
<span style="margin-left:5px;">Страница</span></a>
<!--Закрываем абзац-->
</p>
<p>
<a href="">
<img src="http://trueimages.ru/img/31/ab/4dcb087c2ae4305edcd15171696.jpg">
<span style="margin-left:5px;">Страница 1</span;></a>
</p>
<p>
<a href="">
<img src="http://trueimages.ru/img/31/ab/4dcb087c2ae4305edcd15171696.jpg">
<span style="margin-left:5px;">Страница 2</span></a>
</p>
<!--Закрываем строку Меню-->
</td>
</tr>
<!--Создаём строку с дополнительной информацией-->
<tr>
<!--Ячейка с дополнительной информацией-->
<td
bgcolor="#e6e6fa"
align="center">
<h3>Общая информация</h3>
<p>Текст общей информации или реклама</p>
<!--Закрываем ячейку с общей информацией
и таблицу основного контента-->
</td>
</tr>
</table>
<!--ПОДВАЛ-->
<!--Создаём таблицу подвала-->
<table
border="1"
bgcolor="#7FFFD4"
height="100"
cellpadding="10"
style="width:100%; border-radius:5px;">
<!--Создаём строку.-->
<tr>
<!--Создаём столбец-->
<th>
<h3>Подвал</h3>
<!--Закрываем таблицу подвала. При желании в подвале можно
сделать несколько строк и столбцов-->
</th>
</tr>
</table>
<!--Закрываем таблицу контейнера-->
</td>
</tr>
</table>
</body>
</html>

View File

@@ -82,7 +82,7 @@ std::string CgiHandle::executeCgi()
int byte_read = 1; int byte_read = 1;
std::string body; std::string body;
argv[0] = const_cast<char *>(_response.getCgiPass().data()); argv[0] = const_cast<char *>(_response._fullURI.data());
argv[1] = NULL; argv[1] = NULL;
try try
{ {
@@ -92,7 +92,6 @@ std::string CgiHandle::executeCgi()
{ {
std::cerr << RED << e.what() << RESET << '\n'; std::cerr << RED << e.what() << RESET << '\n';
} }
printenv(env);
sI = dup(STDIN_FILENO); sI = dup(STDIN_FILENO);
sO = dup(STDOUT_FILENO); sO = dup(STDOUT_FILENO);
@@ -100,9 +99,9 @@ std::string CgiHandle::executeCgi()
FILE *fOt = tmpfile(); FILE *fOt = tmpfile();
long fdin = fileno(fIn); long fdin = fileno(fIn);
long fdOut = fileno(fOt); long fdOut = fileno(fOt);
DBOUT << BLUE << "in CGI exe" << ENDL; if (_request.getBody() != NULL)
// DBOUT << "BODY[\n" << _request.getBody() << "\n]" << ENDL; write(fdin, _request.getBody()->data(), _request.getBody()->size());
write(fdin, _request.getBody().data(), _request.getBody().size());
lseek(fdin, 0, SEEK_SET); lseek(fdin, 0, SEEK_SET);
pid = fork(); pid = fork();
if (pid == -1) if (pid == -1)
@@ -124,9 +123,10 @@ std::string CgiHandle::executeCgi()
waitpid(-1, NULL, 0); waitpid(-1, NULL, 0);
lseek(fdOut, 0, SEEK_SET); lseek(fdOut, 0, SEEK_SET);
byte_read = 1;
while (byte_read) while (byte_read)
{ {
bzero(buffer, BUFFSIZE); memset(buffer, 0, BUFFSIZE + 1);
byte_read = read(fdOut, buffer, BUFFSIZE); byte_read = read(fdOut, buffer, BUFFSIZE);
body.append(buffer, byte_read); body.append(buffer, byte_read);
} }
@@ -147,21 +147,21 @@ void CgiHandle::initEnvVariables()
{ {
std::map<std::string, std::string>::iterator it; std::map<std::string, std::string>::iterator it;
std::map<std::string, std::string> tmp1 = _request.getClientFields(); std::map<std::string, std::string> tmp1 = _request.getClientFields();
_scriptName = _response.getFullURI().substr(_response.getFullURI().rfind("/")); _scriptName = _response._fullURI.substr(_response._fullURI.rfind("/"));
it = tmp1.find("content_type"); it = tmp1.find("content_type");
if (it != tmp1.end()) if (it != tmp1.end())
_variable["AUTH TYPE"] = it->second; _variable["AUTH TYPE"] = it->second;
else else
_variable["AUTH TYPE"] = ""; _variable["AUTH TYPE"] = "";
_variable["CONTENT_LENGTH"] = toString(_request.getContentLength()); _variable["CONTENT_LENGTH"] = (_request.getBody() == NULL) ? "0" : toString(_request.getBody()->size());
it = _request.getClientFields().find("content-type"); it = _request.getClientFields().find("content-type");
_variable["CONTENT_TYPE"] = ""; _variable["CONTENT_TYPE"] = "";
_variable["GATEWAY_INTERFACE"] = std::string("CGI/1.1"); _variable["GATEWAY_INTERFACE"] = std::string("CGI/1.1");
_variable["SCRIPT_NAME"] = _response.getFullURI(); _variable["SCRIPT_NAME"] = _response._fullURI;
_variable["SCRIPT_FILENAME"] = _response.getFullURI(); _variable["SCRIPT_FILENAME"] = _response._fullURI;
_variable["PATH_TRANSLATED"] = _response.getFullURI(); _variable["PATH_TRANSLATED"] = _request.getURI();
_variable["REQUEST_URI"] = _request.getURI(); _variable["REQUEST_URI"] = _request.getURI();
_variable["PATH_INFO"] = _request.getURI(); _variable["PATH_INFO"] = _request.getURI();
@@ -184,7 +184,7 @@ void CgiHandle::initEnvVariables()
tmp = getEnvFormat(it->first); tmp = getEnvFormat(it->first);
_variable["HTTP_" + tmp] = it->second; _variable["HTTP_" + tmp] = it->second;
} }
printSSmap(_variable); // printSSmap(_variable);
} }
CgiHandle::~CgiHandle() CgiHandle::~CgiHandle()

View File

@@ -111,7 +111,7 @@ bool Client::isChunked(void)
// Возвращает истина, если отправлены все данные клиента. // Возвращает истина, если отправлены все данные клиента.
bool Client::allSended(void) bool Client::allSended(void)
{ {
if (_toSend.size() <= _sended) if (response_len <= _sended)
done = true; done = true;
return (done); return (done);
} }
@@ -135,59 +135,64 @@ void Client::increaseRecvCounter(unsigned int n)
} }
//Генерирует response. Далее респонс можно получить через функцию getStrToSend() //Генерирует response. Далее респонс можно получить через функцию getStrToSend()
int Client::sendResponse(int fd) // int Client::sendResponse(int fd)
{ // {
_response.setData(_request, _config); // _response.setData(_request, _config);
_response.generate(); // _response.generate();
_headerToSend = _response.getHeader(); // _headerToSend = _response.getHeader();
_bodyToSend = _response.getBody(); // _bodyToSend = _response.getBody();
_ret = sendData(fd, _headerToSend + _bodyToSend); // _ret = sendData(fd, _headerToSend + _bodyToSend);
return (_ret); // return (_ret);
} // }
std::string Client::generateRespons(void) // std::string Client::generateRespons(void)
{ // {
size_t len; // size_t len;
_response.setData(_request, _config); // _response.setData(_request, _config);
_response.generate(); // _response.generate();
_headerToSend = _response.getHeader(); // _headerToSend = _response.getHeader();
_bodyToSend = _response.getBody(); // _bodyToSend = _response.getBody();
_toSend = _headerToSend + _bodyToSend; // *_toSend = _headerToSend + _bodyToSend;
len = _toSend.size(); // len = _toSend->size();
response_len = len; // response_len = len;
_to_send_char = new char[len + 1]; // _to_send_char = new char[len + 1];
std::memcpy(_to_send_char, _toSend.c_str(), len + 1); // std::memcpy(_to_send_char, _toSend->c_str(), len + 1);
// DBOUT << "len = " << len << ENDL; // return (*_toSend);
// DBOUT << "strlen = " << strlen(_to_send_char) << ENDL; // }
// DBOUT << "content_lenth = " << _request.getContentLength() << ENDL;
return (_toSend);
}
std::string Client::generateRespons(std::vector<ServerConfig *> &configs) std::string Client::generateRespons(std::vector<ServerConfig *> &configs)
{ {
size_t len; size_t len;
location *tmp; std::vector<location *> tmp;
_config = Config::getConfig(configs, _request, connected_to); _config = Config::getConfig(configs, _request, connected_to);
tmp = Config::getLocation(_config->getLocations(), _request.getURI()); tmp = Config::getLocation(_config->getLocations(), _request.getURI());
_response.setData(_request, _config, tmp); _response.setData(_request, _config, tmp);
_response.generate2(connected_to); _response.generate2(connected_to);
_headerToSend = _response.getHeader();
_bodyToSend = _response.getBody(); _toSend = new std::string;
_toSend = _headerToSend + _bodyToSend; *_toSend = (_response.getBody() == NULL) ? _response.getHeader() : _response.getHeader() + *_response.getBody();
len = _toSend.size(); len = _toSend->size();
response_len = len; response_len = len;
_to_send_char = new char[len + 1]; _to_send_char = new char[len + 1];
std::memcpy(_to_send_char, _toSend.c_str(), len + 1); std::memcpy(_to_send_char, _toSend->c_str(), len + 1);
return (_toSend); std::cout << PINK << "\n[["<< YELLOW << "Request header\n{" << ENDL;
std::cout << BLUE << _request.getHeader() << YELLOW << "},\n" << ENDL;
std::cout << GREEN << "Response Header\n{" << ENDL;
std::cout << BLUE << _response.getHeader() << GREEN << "}" << PINK << "]]\n"<< ENDL;
delete _toSend;
if (_request.getBody() != NULL)
_request.freeData();
_response.freeData();
return (_headerToSend);
} }
//-------------------------------------------------Error--------------------------------------- //-------------------------------------------------Error---------------------------------------
@@ -261,7 +266,6 @@ void Client::clear(void)
_config = NULL; _config = NULL;
_bodyToSend = ""; _bodyToSend = "";
_headerToSend = ""; _headerToSend = "";
_toSend = "";
if (_to_send_char) if (_to_send_char)
delete[] _to_send_char; delete[] _to_send_char;
} }

View File

@@ -26,7 +26,7 @@ private:
std::string _stringBUF; std::string _stringBUF;
std::string _bodyToSend; std::string _bodyToSend;
std::string _headerToSend; std::string _headerToSend;
std::string _toSend; std::string *_toSend;
char *_to_send_char; char *_to_send_char;
std::map<std::string, std::string> _errorCode; std::map<std::string, std::string> _errorCode;

View File

@@ -36,6 +36,21 @@ int isDir(std::string path)
return (-1); return (-1);
return (-1); return (-1);
} }
void copyLocation(location *dest, location *src)
{
dest->autoindex = src->autoindex;
dest->cgi_pass = src->cgi_pass;
dest->clientBodySize = src->clientBodySize;
dest->directoryFile = src->directoryFile;
dest->location = src->location;
dest->methods = src->methods;
dest->redirect = src->redirect;
dest->root = src->root;
dest->uploadAccept = src->uploadAccept;
dest->uploadDir = src->uploadDir;
}
int Config::calcLen(std::string &s1, std::string &s2) int Config::calcLen(std::string &s1, std::string &s2)
{ {
unsigned long len = 0; unsigned long len = 0;
@@ -48,7 +63,7 @@ int Config::calcLen(std::string &s1, std::string &s2)
return (len); return (len);
} }
location *Config::getLocation(std::vector<location *> &arr, std::string &URI) std::vector<location *> Config::getLocation(std::vector<location *> &arr, std::string &URI)
{ {
unsigned int tryLen = URI.size(); unsigned int tryLen = URI.size();
std::string tryLocation; std::string tryLocation;
@@ -57,6 +72,7 @@ location *Config::getLocation(std::vector<location *> &arr, std::string &URI)
std::string suffix1; std::string suffix1;
std::vector<location *>::iterator it; std::vector<location *>::iterator it;
std::vector<location *> step_1; std::vector<location *> step_1;
std::vector<location *> step_2;
suffix = URI.substr(URI.rfind(".") + 1, URI.size() - URI.rfind(".")); suffix = URI.substr(URI.rfind(".") + 1, URI.size() - URI.rfind("."));
while (tryLen) while (tryLen)
@@ -79,7 +95,7 @@ location *Config::getLocation(std::vector<location *> &arr, std::string &URI)
it = step_1.begin(); it = step_1.begin();
tmp = *it; tmp = *it;
if (tmp->location == URI || tmp->location.size() > 1) if (tmp->location == URI || tmp->location.size() > 1)
return (tmp); step_2.push_back(tmp);
} }
it = arr.begin(); it = arr.begin();
@@ -90,20 +106,22 @@ location *Config::getLocation(std::vector<location *> &arr, std::string &URI)
{ {
suffix1 = tmp->location.substr(2); suffix1 = tmp->location.substr(2);
if (suffix1 == suffix) if (suffix1 == suffix)
return (tmp); step_2.push_back(tmp);
} }
it++; it++;
} }
it = arr.begin(); if (step_2.empty())
while (it != arr.end())
{ {
tmp = *it; it = arr.begin();
if (tmp->location == "/") while (it != arr.end())
return (tmp); {
it++; tmp = *it;
if (tmp->location == "/")
step_2.push_back(tmp);
it++;
}
} }
return (step_2);
return (NULL);
} }
ServerConfig *Config::getConfig(std::vector<ServerConfig *> &arr, Request &request, serverListen &data) ServerConfig *Config::getConfig(std::vector<ServerConfig *> &arr, Request &request, serverListen &data)

View File

@@ -16,7 +16,7 @@ public:
~Config(); ~Config();
static int calcLen(std::string &, std::string &); static int calcLen(std::string &, std::string &);
static location *getLocation(std::vector<location *> &, std::string &URI); static std::vector<location *> getLocation(std::vector<location *> &, std::string &URI);
static ServerConfig *getConfig(std::vector<ServerConfig *> &, Request &request, serverListen &data); static ServerConfig *getConfig(std::vector<ServerConfig *> &, Request &request, serverListen &data);
private: private:

View File

@@ -13,7 +13,7 @@ Request::Request()
_received = 0; _received = 0;
_headerSize = 0; _headerSize = 0;
_lifeTime = 5; _lifeTime = 5;
_body = NULL;
} }
Request::Request(char *str) Request::Request(char *str)
@@ -28,15 +28,22 @@ Request::Request(char *str)
_contentLength = 0; _contentLength = 0;
_headerSize = 0; _headerSize = 0;
_lifeTime = 5; _lifeTime = 5;
_body = NULL;
} }
//-------------------------------------------------Get/Set--------------------------------------- //-------------------------------------------------Get/Set---------------------------------------
void Request::freeData(void)
{
delete _body;
}
std::string &Request::getURI(void) std::string &Request::getURI(void)
{ {
return (_URI); return (_URI);
} }
std::string &Request::getBody(void) std::string *Request::getBody(void)
{ {
return (_body); return (_body);
} }
@@ -89,7 +96,7 @@ bool Request::getChunked(void)
return (_chunked); return (_chunked);
} }
unsigned int Request::getContentLength(void) const ssize_t Request::getContentLength(void) const
{ {
return (_contentLength); return (_contentLength);
} }
@@ -97,10 +104,14 @@ unsigned int Request::getHeaderSize(void) const
{ {
return (_headerSize); return (_headerSize);
} }
unsigned int Request::getRecved(void) const ssize_t Request::getRecved(void) const
{ {
return (_received); return (_received);
} }
std::string &Request::getHeader(void)
{
return _head;
}
void Request::setData(char *str) void Request::setData(char *str)
{ {
this->_data = str; this->_data = str;
@@ -127,6 +138,25 @@ void Request::increaseRecvCounter(unsigned int n)
{ {
_received += n; _received += n;
} }
std::string urlDecode(std::string &url) {
std::string ret;
char ch;
size_t i, ii;
for (i=0; i < url.length(); i++) {
if (size_t(url[i])==37) {
sscanf(url.substr(i+1,2).c_str(), "%lx", &ii);
ch=static_cast<char>(ii);
ret+=ch;
i=i+2;
} else {
ret+=url[i];
}
}
return (ret);
}
void Request::parseURI(std::string str) void Request::parseURI(std::string str)
{ {
std::string tmp; std::string tmp;
@@ -141,6 +171,10 @@ void Request::parseURI(std::string str)
} }
else else
_URI = str; _URI = str;
std::string sIn = _URI;
_URI = urlDecode(sIn);
_fullURI = HOME + _URI; _fullURI = HOME + _URI;
} }
@@ -196,24 +230,25 @@ void Request::splitData(std::string &data)
str = _head.substr(_headerSize); str = _head.substr(_headerSize);
_head = tmp; _head = tmp;
_head_ok = true; _head_ok = true;
parseHeader(); parseHeader();
if ((_contentLength == 0 && !_chunked) || (_method == "GET" if ((_contentLength == 0 && !_chunked) || (_method == "GET"
|| _method == "DELETE" || _method == "HEAD")) || _method == "DELETE" || _method == "HEAD"))
_body_ok = true; _body_ok = true;
else
_body = new std::string;
} }
} }
if (badCode(_ret)) if (badCode(_ret))
return ; return ;
else if (_chunked) else if (_chunked && !_body_ok)
{ {
_body.insert(_body.end(), str.begin(), str.end()); _body->insert(_body->end(), str.begin(), str.end());
if (checkEnd(_body, "0\r\n\r\n") == 0) if (checkEnd(*_body, "0\r\n\r\n") == 0)
_body_ok = true; _body_ok = true;
} }
else if (_head_ok && !_body_ok) else if (_head_ok && !_body_ok)
{ {
_body.insert(_body.end(), str.begin(), str.end()); _body->insert(_body->end(), str.begin(), str.end());
if ((_received - _headerSize) == _contentLength) if ((_received - _headerSize) == _contentLength)
{ {
_body_ok = true; _body_ok = true;
@@ -221,7 +256,7 @@ void Request::splitData(std::string &data)
} }
if (_head_ok && _body_ok && _chunked) if (_head_ok && _body_ok && _chunked)
{ {
std::string &tmp = _body; std::string &tmp = *_body;
std::string subchunk = tmp.substr(0, 100); std::string subchunk = tmp.substr(0, 100);
std::string newBody = ""; std::string newBody = "";
int chunksize = strtol(subchunk.c_str(), NULL, 16); int chunksize = strtol(subchunk.c_str(), NULL, 16);
@@ -235,7 +270,7 @@ void Request::splitData(std::string &data)
subchunk = tmp.substr(i, 100); subchunk = tmp.substr(i, 100);
chunksize = strtol(subchunk.c_str(), NULL, 16); chunksize = strtol(subchunk.c_str(), NULL, 16);
} }
_body = newBody; *_body = newBody;
} }
} }
@@ -380,7 +415,6 @@ void Request::clear(void)
_ret = 200; _ret = 200;
_row = 0; _row = 0;
_URI = ""; _URI = "";
_body = "";
_host = ""; _host = "";
_query = ""; _query = "";
_method = ""; _method = "";

View File

@@ -14,13 +14,13 @@ private:
int _ret; int _ret;
int _row; int _row;
int _lifeTime; int _lifeTime;
unsigned int _contentLength; ssize_t _contentLength;
unsigned int _received; ssize_t _received;
unsigned int _headerSize; unsigned int _headerSize;
std::string _URI; std::string _URI;
std::string _head; std::string _head;
std::string _body; std::string *_body;
std::string _host; std::string _host;
std::string _query; std::string _query;
std::string _method; std::string _method;
@@ -37,7 +37,7 @@ private:
bool _chunked; bool _chunked;
public: public:
std::string &getURI(void); std::string &getURI(void);
std::string &getBody(void); std::string *getBody(void);
std::string &getHost(void); std::string &getHost(void);
std::string &getQuery(void); std::string &getQuery(void);
std::string &getMethod(void); std::string &getMethod(void);
@@ -48,9 +48,9 @@ public:
ServerConfig *getConfig(void); ServerConfig *getConfig(void);
int getCode(void); int getCode(void);
int getLifeTime(void); int getLifeTime(void);
unsigned int getContentLength(void) const; ssize_t getContentLength(void) const;
unsigned int getHeaderSize(void) const; unsigned int getHeaderSize(void) const;
unsigned int getRecved(void)const; ssize_t getRecved(void)const;
char *getPointerBody(void)const; char *getPointerBody(void)const;
std::map<std::string, std::string> getClientFields(void); std::map<std::string, std::string> getClientFields(void);
@@ -81,6 +81,8 @@ public:
void copyFromMap(void); void copyFromMap(void);
void clear(void); void clear(void);
void splitData(std::string &); void splitData(std::string &);
void freeData(void);
std::string &getHeader(void);
void increaseRecvCounter(unsigned int n); void increaseRecvCounter(unsigned int n);
~Request(); ~Request();

View File

@@ -6,16 +6,25 @@ Response::Response()
{ {
initErrorCode(); initErrorCode();
_Autoindex = true; _Autoindex = true;
_body = NULL;
_header = NULL;
_code = 200; _code = 200;
} }
//-------------------------------------------------GET/SET--------------------------------------- //-------------------------------------------------GET/SET---------------------------------------
void Response::freeData(void)
{
if (_body != NULL)
delete _body;
delete _header;
}
std::string Response::getHeader(void) std::string Response::getHeader(void)
{ {
return (_header); return (*_header);
} }
std::string Response::getBody(void) std::string *Response::getBody(void)
{ {
return (_body); return (_body);
} }
@@ -27,12 +36,21 @@ void Response::setData(Request request, ServerConfig *config)
_config = config; _config = config;
} }
void Response::setData(Request &request, ServerConfig *config, location *loc) void Response::setData(Request &request, ServerConfig *config, std::vector<location *> &loc)
{ {
_request = request; _request = request;
_code = request.getCode(); _code = request.getCode();
_config = config; _config = config;
_location = loc; if (loc.empty())
_code = 404;
else
{
_location = loc[0];
if (loc.size() == 2)
_cgi_Pass = loc[1]->cgi_pass;
else
_cgi_Pass = _location->cgi_pass;
}
} }
void Response::setHeaderBlocks(void) void Response::setHeaderBlocks(void)
@@ -59,7 +77,10 @@ void Response::setContentType(void)
void Response::setContentLength() void Response::setContentLength()
{ {
_contentLength = _body.size(); if (_body != NULL)
_contentLength = _body->size();
else
_contentLength = 0;
} }
void Response::setServer(void) void Response::setServer(void)
@@ -100,21 +121,25 @@ serverListen Response::getListen()
std::string Response::getCgiPass(void) std::string Response::getCgiPass(void)
{ {
return (_location->cgi_pass); return (_cgi_Pass);
}
ssize_t Response::getMaxBodySize(void)
{
return (_maxBodySize);
} }
//-------------------------------------------------File--------------------------------------- //-------------------------------------------------File---------------------------------------
void Response::OpenResponseFile(const char *path) void Response::OpenResponseFile(const char *path)
{ {
DBOUT << "in OPEN RESPONSE FILE " << path << ENDL;
std::stringstream ss; std::stringstream ss;
std::ifstream file(path, std::ifstream::in); std::ifstream file(path, std::ifstream::in);
if (file.is_open()) if (file.is_open())
{ {
ss << file.rdbuf(); ss << file.rdbuf();
_body = ss.str(); *_body = ss.str();
file.close(); file.close();
} }
else else
@@ -138,14 +163,14 @@ void Response::OpenErrorFile(int code)
if (file.is_open()) if (file.is_open())
{ {
ss << file.rdbuf(); ss << file.rdbuf();
_body = ss.str(); *_body = ss.str();
file.close(); file.close();
} }
else else
_body = getErrorPage(code); *_body = getErrorPage(code);
} }
else else
_body = getErrorPage(code); *_body = getErrorPage(code);
} }
std::string Response::getContentType(void) std::string Response::getContentType(void)
@@ -205,15 +230,16 @@ std::string Response::getFullURI(void)
int pos = 0; int pos = 0;
pos = _request.getURI().rfind("/"); pos = _request.getURI().rfind("/");
tmp = _request.getURI().substr(pos); tmp = _request.getURI().substr(pos);
if (!_location->uploadDir.empty())
_upload_dir = _location->uploadDir + tmp;
tmp = _location->root + tmp; tmp = _location->root + tmp;
} }
else else
{ {
DBOUT << "location" << _location->location << ENDL;
tmp = _request.getURI().substr(len); tmp = _request.getURI().substr(len);
DBOUT << "tmp1 " << RED << tmp << ENDL; if (!_location->uploadDir.empty())
_upload_dir = _location->uploadDir + tmp;
tmp = _location->root + tmp; tmp = _location->root + tmp;
DBOUT << "tmp2" << RED << tmp << ENDL;
} }
if (_request.isDir(tmp) == 0) if (_request.isDir(tmp) == 0)
{ {
@@ -226,7 +252,11 @@ std::string Response::getFullURI(void)
} }
else else
ret = tmp; ret = tmp;
if (_upload_dir.empty())
_upload_dir = ret;
DBOUT << PINK << "location " << _location->location << ENDL;
DBOUT << PINK << "fullURI " << ret << ENDL;
DBOUT << PINK << "upload dir " << _upload_dir << ENDL;
return (ret); return (ret);
} }
@@ -236,8 +266,8 @@ void Response::generateBody(void)
{ {
if (_Autoindex) if (_Autoindex)
{ {
_body = Autoindex::getPage(_request.getURI(), _fullURI, _request.getHost(), _listen.port); *_body = Autoindex::getPage(_request.getURI(), _fullURI, _request.getHost(), _listen.port);
if (_body.empty()) if (_body->empty())
_code = 404; _code = 404;
} }
else else
@@ -263,16 +293,17 @@ bool Response::allowedMethod(std::string &method)
{ {
if (*it == method) if (*it == method)
return (true); return (true);
DBOUT << BLUE << *it << ENDL;
it++; it++;
} }
if (_location->cgi_pass.empty()) if (!_cgi_Pass.empty() && (method == "GET" || method == "POST"))
_code = 405; return (true);
_code = 405;
return (false); return (false);
} }
void Response::generateHeader(void) void Response::generateHeader(void)
{ {
_header = new std::string;
std::stringstream ss; std::stringstream ss;
std::string tmp; std::string tmp;
@@ -281,15 +312,15 @@ void Response::generateHeader(void)
ss << "Content-Type: " << _contentType << "\r\n"; ss << "Content-Type: " << _contentType << "\r\n";
ss << "Content-Length: " << _contentLength << "\r\n"; ss << "Content-Length: " << _contentLength << "\r\n";
ss << "Server: " << _server << "\r\n"; ss << "Server: " << _server << "\r\n";
if (!_keepAlive.empty()) // if (!_keepAlive.empty())
ss << "Keep-Alive: " <<_keepAlive << "\r\n"; // ss << "Keep-Alive: " <<_keepAlive << "\r\n";
ss << "Date: " << _date << "\r\n"; ss << "Date: " << _date << "\r\n";
if (!_cacheControl.empty()) if (!_cacheControl.empty())
ss << "Cache-Control: " << _cacheControl << "\r\n"; ss << "Cache-Control: " << _cacheControl << "\r\n";
if (!_locationSTR.empty()) if (!_locationSTR.empty())
ss << "Location: " << _locationSTR << "\r\n"; ss << "Location: " << _locationSTR << "\r\n";
ss << "\r\n"; ss << "\r\n";
_header = ss.str(); *_header = ss.str();
} }
void Response::generate() void Response::generate()
@@ -311,7 +342,7 @@ void Response::generate2(serverListen &l)
{ {
_code = 404; _code = 404;
} }
else else if (!_request.badCode(_code))
{ {
_listen = l; _listen = l;
_errorPages = _config->getErrorPages(); _errorPages = _config->getErrorPages();
@@ -322,18 +353,10 @@ void Response::generate2(serverListen &l)
_fullURI = getFullURI(); _fullURI = getFullURI();
_method = _request.getMethod(); _method = _request.getMethod();
_maxBodySize = (_location->clientBodySize > 0) ? _location->clientBodySize : _config->getClientBodySize(); _maxBodySize = (_location->clientBodySize > 0) ? _location->clientBodySize : _config->getClientBodySize();
if (_maxBodySize > 0) if (_maxBodySize > 0 && _request.getBody() != NULL)
_code = (_request.getRecved() > _maxBodySize) ? 413 : _code; _code = (_request.getBody()->size() > (unsigned long)_maxBodySize) ? 413 : _code;
DBOUT << BLUE << "max size" << _maxBodySize << ENDL;
DBOUT << BLUE << "_location size" << _location->clientBodySize << ENDL;
DBOUT << BLUE << "_config sieze" << _config->getClientBodySize() << ENDL;
DBOUT << BLUE << "req size " << _request.getContentLength() << ENDL;
DBOUT << BLUE << "recv size " << _request.getRecved() << ENDL;
} }
if (_request.badCode(_code) || !allowedMethod(_method) || isRedirect())
DBOUT << "fullURI " << _fullURI << ENDL;
DBOUT << RED << "code is " << _code << ENDL;
if (_request.badCode(_code) || (!allowedMethod(_method) && _location->cgi_pass.empty()) || isRedirect())
{ {
invalidClient(); invalidClient();
return; return;
@@ -364,6 +387,7 @@ bool Response::isRedirect()
void Response::invalidClient(void) void Response::invalidClient(void)
{ {
_body = new std::string;
if (!isRedirect()) if (!isRedirect())
OpenErrorFile(_code); OpenErrorFile(_code);
setHeaderBlocks(); setHeaderBlocks();
@@ -375,58 +399,56 @@ void Response::invalidClient(void)
void Response::methodGet(void) void Response::methodGet(void)
{ {
if (!_location->cgi_pass.empty()) _body = new std::string;
if (!_cgi_Pass.empty())
{ {
CgiHandle cgi(_request, *this); CgiHandle cgi(_request, *this);
_body = cgi.executeCgi(); *_body = cgi.executeCgi();
unsigned long pos = _body.find("\r\n\r\n");
unsigned long pos = _body->find("\r\n\r\n");
if (pos != std::string::npos) if (pos != std::string::npos)
{ {
std::string tmp = _body.substr(0, pos); std::string tmp = _body->substr(0, pos);
unsigned long stat = tmp.find("Status: "); unsigned long stat = tmp.find("Status: ");
unsigned long type = tmp.find("Content-type: "); unsigned long type = tmp.find("Content-type: ");
if (stat != std::string::npos) if (stat != std::string::npos)
_code = atoi(tmp.substr(stat + 8, 3).c_str()); _code = atoi(tmp.substr(stat + 8, 3).c_str());
if (type != std::string::npos) if (type != std::string::npos)
_contentType = tmp.substr(type + 14, tmp.find("\r\n", type+14)); _contentType = tmp.substr(type + 14, tmp.find("\r\n", type+14));
_body.erase(_body.begin(), _body.begin() + pos + 4); _body->erase(_body->begin(), _body->begin() + pos + 4);
} }
} }
else else
generateBody(); generateBody();
setHeaderBlocks(); setHeaderBlocks();
generateHeader(); generateHeader();
std::cout << GREEN << "GET method called\n" << ZERO_C; DBOUT << GREEN << "GET method called\n" << ZERO_C;
} }
void Response::methodPost(void) void Response::methodPost(void)
{ {
if (!_location->cgi_pass.empty()) if (!_cgi_Pass.empty())
{ {
_body = new std::string;
CgiHandle cgi(_request, *this); CgiHandle cgi(_request, *this);
_body = cgi.executeCgi(); *_body = cgi.executeCgi();
unsigned long pos = _body.find("\r\n\r\n"); DBOUT << "CGI SIZE BODY " << _body->size() << ENDL;
unsigned long pos = _body->find("\r\n\r\n");
if (pos != std::string::npos) if (pos != std::string::npos)
{ {
std::string tmp = _body.substr(0, pos); std::string tmp = _body->substr(0, pos);
unsigned long stat = tmp.find("Status: "); unsigned long stat = tmp.find("Status: ");
unsigned long type = tmp.find("Content-type: "); unsigned long type = tmp.find("Content-type: ");
if (stat != std::string::npos) if (stat != std::string::npos)
_code = atoi(tmp.substr(stat + 8, 3).c_str()); _code = atoi(tmp.substr(stat + 8, 3).c_str());
if (type != std::string::npos) if (type != std::string::npos)
_contentType = tmp.substr(type + 14, tmp.find("\r\n", type+14)); _contentType = tmp.substr(type + 14, tmp.find("\r\n", type+14));
_body.erase(_body.begin(), _body.begin() + pos + 4); _body->erase(_body->begin(), _body->begin() + pos + 4);
} }
} }
else else
{
std::ofstream outfile(_fullURI.c_str(), std::ios::out | std::ios::binary);
outfile.write(_request.getBody().data(), _request.getBody().size());
outfile.close();
_code = 204; _code = 204;
}
setHeaderBlocks(); setHeaderBlocks();
generateHeader(); generateHeader();
DBOUT << GREEN << "POST method called" << ENDL; DBOUT << GREEN << "POST method called" << ENDL;
@@ -435,16 +457,16 @@ void Response::methodPost(void)
void Response::methodPut(void) void Response::methodPut(void)
{ {
_code = 201; _code = 201;
if (_request.isFile(_fullURI) == 0) if (_request.isFile(_upload_dir) == 0)
_code = 204; _code = 204;
std::ofstream file(_fullURI.c_str(), std::ios::out | std::ios::binary); std::ofstream file(_upload_dir.c_str(), std::ios::out | std::ios::binary);
if (!file.is_open()) if (!file.is_open())
_code = 403; _code = 403;
else else
{ {
file.write(_request.getBody().data(), _request.getBody().size()); file.write(_request.getBody()->data(), _request.getBody()->size());
file.close();
} }
file.close();
setHeaderBlocks(); setHeaderBlocks();
generateHeader(); generateHeader();
DBOUT << GREEN << "PUT method called" << ENDL; DBOUT << GREEN << "PUT method called" << ENDL;
@@ -554,4 +576,5 @@ std::string Response::getErrorPage(int code)
Response::~Response() Response::~Response()
{ {
} }

View File

@@ -10,8 +10,8 @@ class Response
{ {
private: private:
serverListen _listen; serverListen _listen;
std::string _body; std::string *_body;
std::string _header; std::string *_header;
Request _request; Request _request;
ServerConfig *_config; ServerConfig *_config;
location *_location; location *_location;
@@ -20,13 +20,12 @@ private:
std::map<int, std::string> _errorPages; std::map<int, std::string> _errorPages;
bool _Autoindex; bool _Autoindex;
serverListen _hostPort; serverListen _hostPort;
std::string _fullURI;
std::string _method; std::string _method;
private: private:
std::string _contentType; std::string _contentType;
unsigned int _contentLength; ssize_t _contentLength;
unsigned int _maxBodySize; ssize_t _maxBodySize;
std::string _server; std::string _server;
std::string _keepAlive; std::string _keepAlive;
std::string _date; std::string _date;
@@ -34,6 +33,8 @@ private:
std::string _locationSTR; std::string _locationSTR;
std::string _contentLanguage; std::string _contentLanguage;
std::string _transferEncoding; std::string _transferEncoding;
std::string _upload_dir;
std::string _cgi_Pass;
void setHeaderBlocks(void); void setHeaderBlocks(void);
void setContentType(void); void setContentType(void);
@@ -62,22 +63,24 @@ public:
serverListen getListen(void); serverListen getListen(void);
std::string getCgiPass(void); std::string getCgiPass(void);
std::string getHeader(void); std::string getHeader(void);
std::string getBody(void); std::string *getBody(void);
static std::string getReasonPhrase(std::string); static std::string getReasonPhrase(std::string);
static std::string getReasonPhrase(int); static std::string getReasonPhrase(int);
std::string getErrorPage(int code); std::string getErrorPage(int code);
std::string getFullURI(); std::string getFullURI();
ssize_t getMaxBodySize(void);
bool isRedirect(void); bool isRedirect(void);
bool allowedMethod(std::string &); bool allowedMethod(std::string &);
void setData(Request, ServerConfig *); void setData(Request, ServerConfig *);
void setData(Request &, ServerConfig *, location *location); void setData(Request &, ServerConfig *, std::vector<location *> &);
public: public:
std::string _fullURI;
void OpenResponseFile(const char *path); void OpenResponseFile(const char *path);
void OpenErrorFile(int code); void OpenErrorFile(int code);
void initErrorCode(void); void initErrorCode(void);
void generate(); void generate();
void generate2(serverListen &); void generate2(serverListen &);
void freeData(void);
Response(); Response();
~Response(); ~Response();

View File

@@ -3,7 +3,6 @@
#include <cassert> #include <cassert>
#include <cstdio> #include <cstdio>
#include <map> #include <map>
// #include "parse.hpp"
#define THREAD_NUM 100 #define THREAD_NUM 100
#define MAX_EVENTS #define MAX_EVENTS
@@ -40,22 +39,21 @@ void Server::readConfig(char *filename)
// TOMLMap *root = NULL; // TOMLMap *root = NULL;
// root = parse(filename); // root = parse(filename);
config::TOMLParser parser(filename); config::TOMLParser parser(filename);
try
{
parser.parse(); parser.parse();
_root = parser.root;
DBOUT << RED << "PARSED !!!" << ENDL;
} // catch (std::domain_error &e)
catch (std::domain_error &e) // {
{ // std::cerr << RED << "FATAL: ";
std::cerr << RED << "FATAL: "; // std::cerr << e.what() << RESET << std::endl;
std::cerr << e.what() << RESET << std::endl; // // root->clear();
// root->clear(); // // config::clean_parsed(parser.root);
config::clean_parsed(parser.root); // // delete parser.root;
// delete parser.root; // // exit(-1);
// exit(-1); // return;
return; //
// }
}
// catch (config::Tokenizer::InvalidToken &e) // catch (config::Tokenizer::InvalidToken &e)
// { // {
// std::cerr << RED << "FATAL: "; // std::cerr << RED << "FATAL: ";
@@ -81,11 +79,9 @@ void Server::readConfig(char *filename)
++it; ++it;
} }
config::clean_parsed(parser.root); DBOUT << RED << "GONNA CLEAN_PARSED" << ENDL;
} }
void Server::sendData(Client &client, int fd) void Server::sendData(Client &client, int fd)
{ {
/* std::string tmp = client.getStrToSend(); */ /* std::string tmp = client.getStrToSend(); */
@@ -141,6 +137,7 @@ void Server::readSocket(Client &client, int fd)
// client.setRawData(buf); // client.setRawData(buf);
client.increaseRecvCounter(bytes_read); client.increaseRecvCounter(bytes_read);
status = client.parseRequest(); status = client.parseRequest();
(void)status;
// client_map[fd].printClientInfo(); // client_map[fd].printClientInfo();
if (client.allRecved()) if (client.allRecved())
@@ -197,6 +194,12 @@ void Server::add_to_epoll_list(int fd, unsigned int ep_events)
<< ENDL; << ENDL;
} }
void sigHandler(int sig)
{
if (sig == SIGINT)
throw ConfigException("SIGINT called. Server shutdown!");
}
void Server::start(void) void Server::start(void)
{ {
/* Socket server_sock(AF_INET, SOCK_STREAM, 0, _port, "127.0.0.1"); */ /* Socket server_sock(AF_INET, SOCK_STREAM, 0, _port, "127.0.0.1"); */
@@ -208,6 +211,7 @@ void Server::start(void)
unsigned int client_events = EPOLLIN; unsigned int client_events = EPOLLIN;
unsigned int server_events = EPOLLIN; unsigned int server_events = EPOLLIN;
std::signal(SIGINT, sigHandler);
_epoll_fd = epoll_create(1337); _epoll_fd = epoll_create(1337);
@@ -254,7 +258,7 @@ void Server::start(void)
{ {
ready_num = epoll_wait(_epoll_fd, _events, MAX_CLIENT, 5000); ready_num = epoll_wait(_epoll_fd, _events, MAX_CLIENT, 5000);
DBOUT << TURQ << "ready_num " << ready_num << ENDL; // DBOUT << TURQ << "ready_num " << ready_num << ENDL;
if (ready_num < 0) if (ready_num < 0)
throw std::logic_error("epoll_ret"); throw std::logic_error("epoll_ret");
@@ -323,6 +327,23 @@ void Server::start(void)
void Server::end(void) void Server::end(void)
{
}
//----------------------------------------------Other------------------------------------------------------------------------------------------------
void Server::checkError(int fd, std::string str)
{
if (fd < 0)
{
DBOUT << RED << "Server ERROR: " << str << ENDL;
exit(1);
}
else
DBOUT << GREEN << "Server SUCCESS: " << str << ENDL;
}
Server::~Server()
{ {
std::vector<ServerConfig *>::iterator pri; std::vector<ServerConfig *>::iterator pri;
std::vector<location *>::iterator loc; std::vector<location *>::iterator loc;
@@ -342,23 +363,8 @@ void Server::end(void)
delete *pri; delete *pri;
pri++; pri++;
} }
}
//----------------------------------------------Other------------------------------------------------------------------------------------------------ config::clean_parsed(_root);
void Server::checkError(int fd, std::string str)
{
if (fd < 0)
{
DBOUT << RED << "Server ERROR: " << str << ENDL;
exit(1);
}
else
DBOUT << GREEN << "Server SUCCESS: " << str << ENDL;
}
Server::~Server()
{
} }

View File

@@ -15,6 +15,8 @@ class Server
private: private:
int _port; int _port;
int _epoll_fd; int _epoll_fd;
TOMLMap *_root;
struct epoll_event _events[MAX_CLIENT]; struct epoll_event _events[MAX_CLIENT];
struct sockaddr_in _addres; struct sockaddr_in _addres;
std::string _ip; std::string _ip;

View File

@@ -33,7 +33,7 @@ int &ServerConfig::getPort(void)
return (_port); return (_port);
} }
int &ServerConfig::getClientBodySize(void) ssize_t &ServerConfig::getClientBodySize(void)
{ {
return (_clientBodySize); return (_clientBodySize);
} }
@@ -90,18 +90,42 @@ void ServerConfig::setRoot(TOMLMap * data)
//--------------------------------------------------Parse-Config--------------------------------------- //--------------------------------------------------Parse-Config---------------------------------------
std::string ServerConfig::getTypestr(toml_node::e_type type)
{
if (type == toml_node::NUM)
return ("NUM");
else if (type == toml_node::ARRAY)
return ("ARRAY");
else if (type == toml_node::BOOL)
return ("BOOL");
else if (type == toml_node::STRING)
return ("STRING");
else if (type == toml_node::MAP)
return ("MAP");
else if (type == toml_node::MAPARRAY)
return ("MAPARRAY");
else
return ("UNKNOWN");
}
std::string ServerConfig::getWrongTypeErrorMSG(std::string field, toml_node::e_type expected, toml_node::e_type received)
{
std::string out = "Wrong type specified in " + field + " field, expected "
+ getTypestr(expected) + ", but received " + getTypestr(received) + "!";
return (out);
}
int ServerConfig::putBodySizeLimit(toml_node *node) int ServerConfig::putBodySizeLimit(toml_node *node)
{ {
if (node->get_type() != toml_node::NUM) if (node->get_type() != toml_node::NUM)
return (1); throw ConfigException(getWrongTypeErrorMSG("body_size_limit", toml_node::NUM, node->get_type()));
_clientBodySize = node->getNum(); _clientBodySize = node->getNum();
if (_clientBodySize < 0)
throw ConfigException("Invalid body_size_limit specified!");
return (0); return (0);
} }
int ServerConfig::putErrorPage(toml_node *node) int ServerConfig::putErrorPage(toml_node *node)
{ {
if (node->get_type() != toml_node::MAP) if (node->get_type() != toml_node::MAP)
return (1); throw ConfigException(getWrongTypeErrorMSG("error_page", toml_node::MAP, node->get_type()));
TOMLMap *map = node->getMap(); TOMLMap *map = node->getMap();
TOMLMap::iterator it; TOMLMap::iterator it;
std::string s; std::string s;
@@ -110,7 +134,7 @@ int ServerConfig::putErrorPage(toml_node *node)
while (it != map->end()) while (it != map->end())
{ {
if (it->second->get_type() != toml_node::STRING) if (it->second->get_type() != toml_node::STRING)
return (1); throw ConfigException(getWrongTypeErrorMSG("error_page path", toml_node::STRING, node->get_type()));
s = it->first; s = it->first;
_errorPages[atoi(s.c_str())] = *it->second->getString(); _errorPages[atoi(s.c_str())] = *it->second->getString();
++it; ++it;
@@ -120,22 +144,27 @@ int ServerConfig::putErrorPage(toml_node *node)
int ServerConfig::putHost(toml_node *node) int ServerConfig::putHost(toml_node *node)
{ {
if (node->get_type() != toml_node::STRING) if (node->get_type() != toml_node::STRING)
return (1); throw ConfigException(getWrongTypeErrorMSG("host", toml_node::STRING, node->get_type()));
_host = *node->getString(); _host = *node->getString();
int ret = inet_addr(_host.c_str());
if (ret == -1)
throw ConfigException("Invalid host specified!");
return (0); return (0);
} }
int ServerConfig::putName(toml_node *node) int ServerConfig::putName(toml_node *node)
{ {
if (node->get_type() != toml_node::STRING) if (node->get_type() != toml_node::STRING)
return (1); throw ConfigException(getWrongTypeErrorMSG("server_name", toml_node::STRING, node->get_type()));
_serverName = *node->getString(); _serverName = *node->getString();
return (0); return (0);
} }
int ServerConfig::putPort(toml_node *node) int ServerConfig::putPort(toml_node *node)
{ {
if (node->get_type() != toml_node::NUM) if (node->get_type() != toml_node::NUM)
return (1); throw ConfigException(getWrongTypeErrorMSG("server_name", toml_node::NUM, node->get_type()));
_port = node->getNum(); _port = node->getNum();
if (_port < 0 || _port > 65536)
throw ConfigException("Invalid port specified!");
return (0); return (0);
} }
@@ -170,62 +199,61 @@ int ServerConfig::putLocation(toml_node *node)
if (it1->first == "location") if (it1->first == "location")
{ {
if (it1->second->get_type() != toml_node::STRING) if (it1->second->get_type() != toml_node::STRING)
continue; throw ConfigException(getWrongTypeErrorMSG("location", toml_node::STRING, it1->second->get_type()));
tmp->location = *it1->second->getString(); tmp->location = *it1->second->getString();
} }
else if (it1->first == "root") else if (it1->first == "root")
{ {
if (it1->second->get_type() != toml_node::STRING) if (it1->second->get_type() != toml_node::STRING)
continue ; throw ConfigException(getWrongTypeErrorMSG("root", toml_node::STRING, it1->second->get_type()));
tmp->root = *it1->second->getString(); tmp->root = *it1->second->getString();
} }
else if (it1->first == "autoindex") else if (it1->first == "autoindex")
{ {
if (it1->second->get_type() != toml_node::BOOL) if (it1->second->get_type() != toml_node::BOOL)
continue ; throw ConfigException(getWrongTypeErrorMSG("autoindex", toml_node::BOOL, it1->second->get_type()));
tmp->autoindex = it1->second->getBool(); tmp->autoindex = it1->second->getBool();
} }
else if (it1->first == "upload_accept") else if (it1->first == "upload_accept")
{ {
if (it1->second->get_type() != toml_node::BOOL) if (it1->second->get_type() != toml_node::BOOL)
continue ; throw ConfigException(getWrongTypeErrorMSG("upload_accept", toml_node::BOOL, it1->second->get_type()));
tmp->uploadAccept = it1->second->getBool(); tmp->uploadAccept = it1->second->getBool();
} }
else if (it1->first == "upload_dir") else if (it1->first == "upload_dir")
{ {
if (it1->second->get_type() != toml_node::STRING) if (it1->second->get_type() != toml_node::STRING)
continue ; throw ConfigException(getWrongTypeErrorMSG("upload_dir", toml_node::STRING, it1->second->get_type()));
tmp->uploadDir = *it1->second->getString(); tmp->uploadDir = *it1->second->getString();
} }
else if (it1->first == "cgi_pass") else if (it1->first == "cgi_pass")
{ {
if (it1->second->get_type() != toml_node::STRING) if (it1->second->get_type() != toml_node::STRING)
continue ; throw ConfigException(getWrongTypeErrorMSG("cgi_pass", toml_node::STRING, it1->second->get_type()));
tmp->cgi_pass = *it1->second->getString(); tmp->cgi_pass = *it1->second->getString();
} }
else if (it1->first == "body_size_limit") else if (it1->first == "body_size_limit")
{ {
DBOUT << "BodySize in locaton" << ENDL; if (it1->second->get_type() != toml_node::NUM)
if (node->get_type() != toml_node::NUM) throw ConfigException(getWrongTypeErrorMSG("body_size_limit", toml_node::NUM, it1->second->get_type()));
continue;
tmp->clientBodySize = it1->second->getNum(); tmp->clientBodySize = it1->second->getNum();
} }
else if (it1->first == "directory_file") else if (it1->first == "directory_file")
{ {
if (it1->second->get_type() != toml_node::STRING) if (it1->second->get_type() != toml_node::STRING)
continue ; throw ConfigException(getWrongTypeErrorMSG("directory_file", toml_node::STRING, it1->second->get_type()));
tmp->directoryFile = *it1->second->getString(); tmp->directoryFile = *it1->second->getString();
} }
else if (it1->first == "methods") else if (it1->first == "methods")
{ {
if (it1->second->get_type() != toml_node::ARRAY) if (it1->second->get_type() != toml_node::ARRAY)
continue ; throw ConfigException(getWrongTypeErrorMSG("methods", toml_node::ARRAY, it1->second->get_type()));
Array = *it1->second->getArray(); Array = *it1->second->getArray();
it2 = Array.begin(); it2 = Array.begin();
while (it2 != Array.end()) while (it2 != Array.end())
{ {
if ((*it2)->get_type() != toml_node::STRING) if ((*it2)->get_type() != toml_node::STRING)
continue ; throw ConfigException(getWrongTypeErrorMSG("methods elem", toml_node::STRING, (*it2)->get_type()));
tmp->methods.push_back(*((*it2)->getString())); tmp->methods.push_back(*((*it2)->getString()));
++it2; ++it2;
} }
@@ -233,15 +261,21 @@ int ServerConfig::putLocation(toml_node *node)
else if (it1->first == "redirect") else if (it1->first == "redirect")
{ {
if (it1->second->get_type() != toml_node::ARRAY) if (it1->second->get_type() != toml_node::ARRAY)
continue ; throw ConfigException(getWrongTypeErrorMSG("redirect", toml_node::ARRAY, it1->second->get_type()));
Array = *it1->second->getArray(); Array = *it1->second->getArray();
if (Array.size() != 2)
throw ConfigException("The redirect field specified the wrong number of arguments!");
it2 = Array.begin(); it2 = Array.begin();
if ((*it2)->get_type() != toml_node::STRING)
throw ConfigException(getWrongTypeErrorMSG("redirect elem", toml_node::STRING, (*it2)->get_type()));
str = *(*it2)->getString(); str = *(*it2)->getString();
++it2; ++it2;
if ((*it2)->get_type() != toml_node::STRING)
throw ConfigException(getWrongTypeErrorMSG("redirect elem", toml_node::STRING, (*it2)->get_type()));
tmp->redirect.insert(std::make_pair(atoi(str.c_str()), *(*it2)->getString())); tmp->redirect.insert(std::make_pair(atoi(str.c_str()), *(*it2)->getString()));
} }
else else
std::cout << RED << it1->first << ZERO_C << std::endl; std::cerr << RED << "Warning: unknown parameter: "<< it1->first << ZERO_C << std::endl;
} }
_locations.push_back(tmp); _locations.push_back(tmp);
it++; it++;
@@ -279,6 +313,86 @@ void ServerConfig::fillFields(void)
ret = identify(block); ret = identify(block);
++block; ++block;
} }
checkConfig();
}
int ServerConfig::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 ServerConfig::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);
}
bool ServerConfig::checkFileAndDir(location *loc)
{
std::string root = loc->root;
std::string upload_dir = loc->uploadDir;
std::string directory_file = loc->directoryFile;
if (!root.empty())
{
if (isDir(root) != 0)
throw ConfigException("Directory " + root + " not found!");
}
if (!upload_dir.empty())
{
if (isDir(upload_dir) != 0)
throw ConfigException("Directory " + upload_dir + " not found!");
}
if (!directory_file.empty())
{
directory_file = root + "/" + directory_file;
if (isFile(directory_file) != 0)
throw ConfigException("File " + directory_file + " not found!");
}
return (true);
}
void ServerConfig::checkConfig(void)
{
if (_host.empty())
throw ConfigException("Host field not set!");
else if (_port == 0)
throw ConfigException("Port field not set!");
std::vector<location *>::iterator it;
it = _locations.begin();
location *tmp;
if (it == _locations.end())
throw ConfigException("Required routing settings are missing!");
while (it != _locations.end())
{
tmp = *it;
if (tmp->location.empty())
throw ConfigException("Location field not set!");
checkFileAndDir(tmp);
it++;
}
} }
void ServerConfig::printFields(void) void ServerConfig::printFields(void)
@@ -290,43 +404,43 @@ void ServerConfig::printFields(void)
it1 = _errorPages.begin(); it1 = _errorPages.begin();
it = _locations.begin(); it = _locations.begin();
std::cout << RED << "-------------------------Server-Start----------------------------------\n" << ZERO_C; DBOUT << RED << "-------------------------Server-Start----------------------------------\n" << ZERO_C;
std::cout << GREEN << "name" << " " << BLUE << _serverName << std::endl; DBOUT << GREEN << "name" << " " << BLUE << _serverName << std::endl;
std::cout << GREEN << "host" << " " << BLUE << _host << std::endl; DBOUT << GREEN << "host" << " " << BLUE << _host << std::endl;
std::cout << GREEN << "port" << " " << BLUE << _port << std::endl; DBOUT << GREEN << "port" << " " << BLUE << _port << std::endl;
std::cout << GREEN << "client_body_size" << " " << BLUE << _clientBodySize << std::endl; DBOUT << GREEN << "client_body_size" << " " << BLUE << _clientBodySize << std::endl;
std::cout << GREEN << "location" << std::endl; DBOUT << GREEN << "location" << std::endl;
while (it != _locations.end()) while (it != _locations.end())
{ {
std::cout << PINK << "------------------------------------------------\n"; DBOUT << PINK << "------------------------------------------------\n";
std::cout << YELLOW << "location " << BLUE << (*it)->location <<std::endl; DBOUT << YELLOW << "location " << BLUE << (*it)->location <<std::endl;
std::cout << YELLOW << "root " << BLUE << (*it)->root <<std::endl; DBOUT << YELLOW << "root " << BLUE << (*it)->root <<std::endl;
std::cout << YELLOW << "directoryFile " << BLUE << (*it)->directoryFile <<std::endl; DBOUT << YELLOW << "directoryFile " << BLUE << (*it)->directoryFile <<std::endl;
std::cout << YELLOW << "uploadDir " << BLUE << (*it)->uploadDir <<std::endl; DBOUT << YELLOW << "uploadDir " << BLUE << (*it)->uploadDir <<std::endl;
std::cout << YELLOW << "autoindex " << BLUE << (*it)->autoindex <<std::endl; DBOUT << YELLOW << "autoindex " << BLUE << (*it)->autoindex <<std::endl;
std::cout << YELLOW << "uploadAccept " << BLUE << (*it)->uploadAccept <<std::endl; DBOUT << YELLOW << "uploadAccept " << BLUE << (*it)->uploadAccept <<std::endl;
std::cout << YELLOW << "cgi_pass " << BLUE << (*it)->cgi_pass <<std::endl; DBOUT << YELLOW << "cgi_pass " << BLUE << (*it)->cgi_pass <<std::endl;
std::cout << YELLOW << "client_body_size " << BLUE << (*it)->clientBodySize <<std::endl; DBOUT << YELLOW << "client_body_size " << BLUE << (*it)->clientBodySize <<std::endl;
std::cout << YELLOW << "methods " << std::endl; DBOUT << YELLOW << "methods " << std::endl;
it2 = (*it)->methods.begin(); it2 = (*it)->methods.begin();
while (it2 != (*it)->methods.end()) while (it2 != (*it)->methods.end())
{ {
std::cout << BLUE << *it2 << " "; DBOUT << BLUE << *it2 << " ";
it2++; it2++;
} }
std::cout << std::endl; DBOUT << std::endl;
it3 = (*it)->redirect.begin(); it3 = (*it)->redirect.begin();
std::cout << YELLOW << "redirection" << RED << " " << it3->first << " " << BLUE << it3->second << std::endl; DBOUT << YELLOW << "redirection" << RED << " " << it3->first << " " << BLUE << it3->second << std::endl;
++it; ++it;
std::cout << PINK << "------------------------------------------------\n"; DBOUT << PINK << "------------------------------------------------\n";
} }
std::cout << GREEN << "error pages" << std::endl; DBOUT << GREEN << "error pages" << std::endl;
while (it1 != _errorPages.end()) while (it1 != _errorPages.end())
{ {
std::cout << YELLOW << it1->first << " " << BLUE << it1->second << std::endl; DBOUT << YELLOW << it1->first << " " << BLUE << it1->second << std::endl;
++it1; ++it1;
} }
std::cout << RED << "-------------------------Server-End------------------------------------\n" << ZERO_C; DBOUT << RED << "-------------------------Server-End------------------------------------\n" << ZERO_C;
} }
ServerConfig::~ServerConfig() ServerConfig::~ServerConfig()

View File

@@ -2,6 +2,7 @@
#define SERVERCONFIG_HPP #define SERVERCONFIG_HPP
#include "webserv.hpp" #include "webserv.hpp"
#include "ConfigException.hpp"
#include "parse.hpp" #include "parse.hpp"
struct location struct location
@@ -15,7 +16,7 @@ struct location
std::vector<std::string> methods; std::vector<std::string> methods;
std::map<int, std::string> redirect; std::map<int, std::string> redirect;
std::string cgi_pass; std::string cgi_pass;
unsigned int clientBodySize; ssize_t clientBodySize;
}; };
struct serverListen struct serverListen
@@ -33,7 +34,7 @@ private:
std::string _serverName; std::string _serverName;
std::string _host; std::string _host;
int _port; int _port;
int _clientBodySize; ssize_t _clientBodySize;
std::map<int, std::string> _errorPages; std::map<int, std::string> _errorPages;
std::vector<location *> _locations; std::vector<location *> _locations;
@@ -47,11 +48,12 @@ public:
void setErrorPages(std::map<int, std::string>); void setErrorPages(std::map<int, std::string>);
void setLocations(std::vector<location *>); void setLocations(std::vector<location *>);
void setRoot(TOMLMap *); void setRoot(TOMLMap *);
void checkConfig(void);
std::string &getServerName(void); std::string &getServerName(void);
std::string &getHost(void); std::string &getHost(void);
int &getPort(void); int &getPort(void);
int &getClientBodySize(void); ssize_t &getClientBodySize(void);
std::vector<location *> &getLocations(void); std::vector<location *> &getLocations(void);
std::map<int, std::string> &getErrorPages(void); std::map<int, std::string> &getErrorPages(void);
TOMLMap *getRoot(void); TOMLMap *getRoot(void);
@@ -67,11 +69,18 @@ private:
int putName(toml_node *); int putName(toml_node *);
int putPort(toml_node *); int putPort(toml_node *);
int putLocation(toml_node *); int putLocation(toml_node *);
std::string getTypestr(toml_node::e_type);
std::string getWrongTypeErrorMSG(std::string field, toml_node::e_type expected, toml_node::e_type received);
bool checkFileAndDir(location *);
int isFile(std::string path);
int isDir(std::string path);
public: public:
void fillFields(void); void fillFields(void);
void printFields(void); void printFields(void);
~ServerConfig(); ~ServerConfig();
}; };

View File

@@ -0,0 +1,17 @@
#ifndef CONFIGEXCEPTION_HPP
#define CONFIGEXCEPTION_HPP
#include "webserv.hpp"
class ConfigException
{
private:
std::string _msg;
public:
ConfigException(std::string const &str) : _msg(str){}
~ConfigException(){}
std::string getMessage() const {return (_msg);}
};
#endif

View File

@@ -9,12 +9,25 @@ int main(int argc, char **argv)
(void)argv; (void)argv;
Server server; Server server;
char *path = (char *)"config/real.toml";
server.readConfig(argv[1]); try
server.setupConfig(); {
server.start(); if (argv[1] != NULL)
server.end(); server.readConfig(argv[1]);
else
server.readConfig(path);
server.start();
}
catch(const ConfigException& e)
{
std::cerr << RED << "\n" << e.getMessage() << '\n' << ENDL;
}
catch (std::domain_error &e)
{
std::cerr << RED << "FATAL: ";
std::cerr << e.what() << RESET << std::endl;
}
return (0);
} }

View File

0
tester/index.html Normal file
View File

BIN
ubuntu_cgi_tester Executable file

Binary file not shown.

17
www/script/index2.php Normal file
View File

@@ -0,0 +1,17 @@
<?php
header('Content-type: image/png', true);
$entityBody = file_get_contents('php://input');
echo($entityBody);
// phpinfo();
// echo ("Content-type:text/html\r\n\r\n");
// echo ("<html>\n");
// echo ("<head>\n");
// echo ("<title>Hello World - First CGI Program</title>\n");
// echo ("</head>\n");
// echo ("<body>\n");
// echo ("<h2>Hello World! This is my first CGI program</h2>\n");
// echo ("</body>\n");
// echo ("</html>\n");
?>