/*
This file is part of libhttpserver
Copyright (C) 2011-2019 Sebastiano Merlino
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
*/
#include
#include
#include
#if defined(__MINGW32__) || defined(__CYGWIN32__)
#define _WINDOWS
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x600
#include
#include
#else
#include
#include
#include
#endif
#include
#include
#include
#include
#include
#include "string_utilities.hpp"
#include "http_utils.hpp"
#pragma GCC diagnostic ignored "-Warray-bounds"
#define CHECK_BIT(var,pos) ((var) & (1sin_addr), to_ret, INET_ADDRSTRLEN);
return to_ret;
}
else
{
throw std::invalid_argument("IP family must be either AF_INET or AF_INET6");
}
}
unsigned short get_port(const struct sockaddr* sa)
{
if (!sa) throw std::invalid_argument("socket pointer is null");
if (sa->sa_family == AF_INET)
{
return ((struct sockaddr_in*) sa)->sin_port;
}
else if (sa->sa_family == AF_INET6)
{
return ((struct sockaddr_in6*) sa)->sin6_port;
}
else
{
throw std::invalid_argument("IP family must be either AF_INET or AF_INET6");
}
}
size_t http_unescape(std::string& val)
{
if (val.empty()) return 0;
int rpos = 0;
int wpos = 0;
unsigned int num;
while ('\0' != val[rpos])
{
switch (val[rpos])
{
case '+':
val[wpos] = ' ';
wpos++;
rpos++;
break;
case '%':
if ( (1 == sscanf (val.substr(rpos + 1).c_str(), "%2x", &num)) ||
(1 == sscanf (val.substr(rpos + 1).c_str(), "%2X", &num))
)
{
val[wpos] = (unsigned char) num;
wpos++;
rpos += 3;
break;
}
/* intentional fall through! */
default:
val[wpos] = val[rpos];
wpos++;
rpos++;
}
}
val[wpos] = '\0'; /* add 0-terminator */
val.resize(wpos);
return wpos; /* = strlen(val) */
}
ip_representation::ip_representation(const struct sockaddr* ip)
{
std::fill(pieces, pieces + 16, 0);
if(ip->sa_family == AF_INET)
{
ip_version = http_utils::IPV4;
for(int i=0;isin_addr))[i];
}
}
else
{
ip_version = http_utils::IPV6;
for (int i = 0; i < 16; i++)
{
pieces[i] = ((u_char*)&(((struct sockaddr_in6 *)ip)->sin6_addr))[i];
}
}
mask = DEFAULT_MASK_VALUE;
}
ip_representation::ip_representation(const std::string& ip)
{
std::vector parts;
mask = DEFAULT_MASK_VALUE;
std::fill(pieces, pieces + 16, 0);
if(ip.find(':') != std::string::npos) //IPV6
{
ip_version = http_utils::IPV6;
parts = string_utilities::string_split(ip, ':', false);
if (parts.size() > 8)
{
throw std::invalid_argument("IP is badly formatted. Max 8 parts in IPV6.");
}
unsigned int omitted = 8 - (parts.size() - 1);
if (omitted != 0)
{
int empty_count = 0;
for (unsigned int i = 0; i < parts.size(); i++)
{
if (parts[i].size() == 0) empty_count++;
}
if (empty_count > 1)
{
if (parts[parts.size() - 1].find(".") != std::string::npos) omitted -= 1;
if (empty_count == 2 && parts[0] == "" && parts[1] == "")
{
omitted += 1;
parts = std::vector(parts.begin() + 1, parts.end());
}
else
{
throw std::invalid_argument("IP is badly formatted. Cannot have more than one omitted segment in IPV6.");
}
}
}
int y = 0;
for (unsigned int i = 0; i < parts.size(); i++)
{
if (parts[i] != "*")
{
if (parts[i].size() == 0)
{
for (unsigned int omitted_idx = 0; omitted_idx < omitted; omitted_idx++)
{
pieces[y] = 0;
pieces[y+1] = 0;
y += 2;
}
continue;
}
if (parts[i].size() < 4)
{
stringstream ss;
ss pieces[i];
b_score += (16 - i) * b.pieces[i];
}
}
if (this_score == b_score &&
((this->pieces[10] == 0x00 || this->pieces[10] == 0xFF) && (b.pieces[10] == 0x00 || b.pieces[10] == 0xFF)) &&
((this->pieces[11] == 0x00 || this->pieces[11] == 0xFF) && (b.pieces[11] == 0x00 || b.pieces[11] == 0xFF))
)
{
return false;
}
for (int i = 10; i < 12; i++)
{
if (CHECK_BIT(this->mask, i) && CHECK_BIT(b.mask, i))
{
this_score += (16 - i) * this->pieces[i];
b_score += (16 - i) * b.pieces[i];
}
}
return this_score < b_score;
}
const std::string load_file (const std::string& filename)
{
ifstream fp(filename.c_str(), ios::in | ios::binary | ios::ate);
if(fp.is_open())
{
std::string content;
fp.seekg(0, fp.end);
content.reserve(fp.tellg());
fp.seekg(0, fp.beg);
content.assign((std::istreambuf_iterator(fp)), std::istreambuf_iterator());
return content;
}
else
{
throw std::invalid_argument("Unable to open file");
}
}
void dump_header_map(std::ostream &os, const std::string &prefix,
const std::map &map)
{
std::map::const_iterator it = map.begin();
std::map::const_iterator end = map.end();
if (map.size()) {
os