332 lines
6.4 KiB
C++
332 lines
6.4 KiB
C++
|
|
#include "utils.hpp"
|
|
|
|
void throw_test()
|
|
{
|
|
static int i = 0;
|
|
++i;
|
|
if (i % 8 == 0)
|
|
throw std::bad_alloc();
|
|
}
|
|
|
|
// notice : the use of getline make it such as
|
|
// it doesn't identify multiple delim as one :
|
|
// " something \n else " -> 1 - something
|
|
// 2 - else
|
|
// is not the same as :
|
|
// " something \n\n else " -> 1 - something
|
|
// 2 -
|
|
// 3 - else
|
|
std::vector<std::string> split(std::string input, char delimiter)
|
|
{
|
|
std::vector<std::string> answer;
|
|
std::stringstream ss(input);
|
|
std::string temp;
|
|
|
|
while (getline(ss, temp, delimiter))
|
|
answer.push_back(temp);
|
|
|
|
return answer;
|
|
}
|
|
|
|
std::vector<std::string>
|
|
split_trim(std::string input, std::string delim, char ctrim)
|
|
{
|
|
std::vector<std::string> split_str;
|
|
std::string tmp;
|
|
size_t start = 0;
|
|
size_t end = 0;
|
|
size_t len = 0;
|
|
|
|
while (end != NPOS)
|
|
{
|
|
end = input.find(delim, start);
|
|
len = end - start;
|
|
if (end == NPOS)
|
|
len = end;
|
|
tmp = input.substr(start, len);
|
|
if (ctrim != '\0')
|
|
tmp = trim(tmp, ctrim);
|
|
if (tmp.size() != 0)
|
|
split_str.push_back( tmp );
|
|
start = end + delim.size();
|
|
}
|
|
return split_str;
|
|
}
|
|
|
|
std::string trim(std::string str, char del)
|
|
{
|
|
size_t pos;
|
|
|
|
// delete leadings del
|
|
pos = str.find_first_not_of(del);
|
|
if (pos == NPOS)
|
|
pos = str.size();
|
|
str = str.substr(pos);
|
|
|
|
// delete trailing del
|
|
pos = str.find_last_not_of(del);
|
|
if (pos != NPOS)
|
|
str = str.substr(0, pos + 1);
|
|
|
|
return str;
|
|
}
|
|
|
|
//// trim a set of char
|
|
//std::string trim(std::string str, std::string del)
|
|
//{
|
|
// std::string new_str;
|
|
//
|
|
// while (new_str.compare(str) != 0)
|
|
// {
|
|
// for (size_t i = 0; i < del.size(); i++)
|
|
// trim(str, del[i]);
|
|
// }
|
|
// return str;
|
|
//}
|
|
|
|
std::string itos(int n)
|
|
{
|
|
std::stringstream strs;
|
|
|
|
strs << n;
|
|
return ( strs.str() );
|
|
}
|
|
|
|
bool isNumeric(std::string str)
|
|
{
|
|
for (size_t i = 0; i < str.length(); i++)
|
|
{
|
|
if (std::isdigit(str[i]) == false)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool isNumeric_btw(int low, int high, std::string str)
|
|
{
|
|
for (size_t i = 0; i < str.length(); i++)
|
|
{
|
|
if (std::isdigit(str[i]) == false)
|
|
return false;
|
|
}
|
|
int n = std::strtol(str.c_str(), NULL, 10);
|
|
if (n < low || n > high)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
http_method str_to_http_method(std::string &str)
|
|
{
|
|
if (str == "GET")
|
|
return GET;
|
|
else if (str == "POST")
|
|
return POST;
|
|
else if (str == "DELETE")
|
|
return DELETE;
|
|
return UNKNOWN;
|
|
}
|
|
|
|
std::string http_methods_to_str(unsigned int methods)
|
|
{
|
|
std::string str;
|
|
|
|
if (methods & GET)
|
|
str.append("GET");
|
|
if (methods & POST)
|
|
{
|
|
if (!str.empty())
|
|
str.append(", ");
|
|
str.append("POST");
|
|
}
|
|
if (methods & DELETE)
|
|
{
|
|
if (!str.empty())
|
|
str.append(", ");
|
|
str.append("DELETE");
|
|
}
|
|
|
|
return (str);
|
|
}
|
|
|
|
# include <iostream>
|
|
|
|
file_type eval_file_type(const std::string &path)
|
|
{
|
|
const char *tmp_path = path.c_str(); // variable superflu ?
|
|
struct stat s;
|
|
|
|
if (stat(tmp_path, &s) != -1)
|
|
{
|
|
if (S_ISREG(s.st_mode))
|
|
return (IS_FILE);
|
|
else if (S_ISDIR(s.st_mode))
|
|
return (IS_DIR);
|
|
}
|
|
else
|
|
{
|
|
std::perror("err stat()");
|
|
}
|
|
|
|
return (IS_OTHER);
|
|
}
|
|
|
|
size_t eval_file_mode(std::string path, int mode)
|
|
{
|
|
if (access(path.c_str(), F_OK) == -1)
|
|
{
|
|
std::perror("err access()");
|
|
return 404; // NOT_FOUND, file doesn't exist
|
|
}
|
|
|
|
if (access(path.c_str(), mode) == -1)
|
|
{
|
|
std::perror("err access()");
|
|
return 403; // FORBIDDEN, file doesn't have execution permission
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
replace_all_substr(
|
|
std::string &str,
|
|
const std::string &ori_substr,
|
|
const std::string &new_substr)
|
|
{
|
|
if (ori_substr.empty())
|
|
return;
|
|
size_t pos = 0;
|
|
while (1)
|
|
{
|
|
pos = str.find(ori_substr, pos);
|
|
if (pos == NPOS)
|
|
break;
|
|
str.replace(pos, ori_substr.size(), new_substr);
|
|
pos += new_substr.size();
|
|
}
|
|
}
|
|
|
|
std::string str_tolower(std::string str)
|
|
{
|
|
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
|
|
return str;
|
|
}
|
|
|
|
// identify a line in a string, by delim (ex. '\n')
|
|
// delete this line from the string (and the following nl sequence characters)
|
|
// and return the deleted line (without the followinf nl sequence characters)
|
|
std::string
|
|
extract_line(std::string & str, size_t pos, std::string delim)
|
|
{
|
|
std::string del_str;
|
|
size_t begin;
|
|
size_t end;
|
|
size_t len;
|
|
|
|
begin = str.rfind(delim, pos);
|
|
if (begin == NPOS)
|
|
begin = 0;
|
|
else if (begin < pos)
|
|
begin += delim.size();
|
|
|
|
end = str.find(delim, pos);
|
|
len = end;
|
|
if (end != NPOS)
|
|
len = end - begin;
|
|
|
|
del_str = str.substr(begin, len);
|
|
str.erase(begin, len + delim.size());
|
|
return del_str;
|
|
}
|
|
|
|
// get a line in a string, by delim
|
|
// same as extract, except it doesn't delete it
|
|
std::string get_line(std::string str, size_t pos, std::string delim)
|
|
{
|
|
std::string ret;
|
|
|
|
ret = ::extract_line(str, pos, delim);
|
|
return ret;
|
|
}
|
|
|
|
size_t
|
|
parse_http_headers (
|
|
std::string headers,
|
|
std::map<std::string, std::string> & fields )
|
|
{
|
|
std::vector<std::string> list;
|
|
std::vector<std::string>::iterator it;
|
|
std::vector<std::string>::iterator it_end;
|
|
size_t err_count = 0;
|
|
size_t pos;
|
|
std::string key;
|
|
std::string val;
|
|
|
|
list = ::split_trim(headers, CRLF, ' ');
|
|
|
|
it_end = list.end();
|
|
for (it = list.begin(); it != it_end; it++)
|
|
{
|
|
pos = (*it).find(':');
|
|
if (pos == NPOS)
|
|
{
|
|
err_count++;
|
|
continue;
|
|
}
|
|
key = (*it).substr(0, pos);
|
|
if ( key.find(' ') != NPOS )
|
|
{
|
|
err_count++;
|
|
continue;
|
|
}
|
|
// bad idea, in cgi we need to have the original value
|
|
// key = ::str_tolower(key); // to make "key" case_insensitive
|
|
val = (*it).substr(pos + 1);
|
|
val = ::trim(val, ' ');
|
|
fields.insert( std::pair<std::string, std::string>(key, val) );
|
|
}
|
|
return err_count;
|
|
}
|
|
|
|
void str_map_key_tolower(std::map<std::string, std::string> & mp)
|
|
{
|
|
std::map<std::string, std::string> new_mp;
|
|
std::map<std::string, std::string>::iterator it;
|
|
std::string key;
|
|
std::string value;
|
|
|
|
for (it = mp.begin(); it != mp.end(); it++)
|
|
{
|
|
key = it->first;
|
|
value = it->second;
|
|
key = ::str_tolower(key);
|
|
new_mp.insert( std::pair<std::string, std::string>(key, value) );
|
|
}
|
|
mp.swap(new_mp);
|
|
}
|
|
|
|
// DEBUG
|
|
void print_special(std::string str)
|
|
{
|
|
char c;
|
|
|
|
for (size_t i = 0; i < str.size(); i++)
|
|
{
|
|
c = str[i];
|
|
if (c == '\r')
|
|
std::cout << YELLOW << "\\r" << RESET;
|
|
else if (c == '\n')
|
|
std::cout << YELLOW << "\\n" << RESET << "\n";
|
|
else
|
|
std::cout << c;
|
|
fflush(stdout);
|
|
}
|
|
}
|
|
|
|
bool operator==(const listen_socket& lhs, int fd)
|
|
{ return lhs.fd == fd; }
|
|
|
|
bool operator==(int fd, const listen_socket& rhs)
|
|
{ return fd == rhs.fd; }
|
|
|