[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/itamago/libhttpserver/master/src/http_utils.cpp [Back]  [Original]

/*
     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 "httpserver/http_utils.hpp"

#if defined(_WIN32) && !defined(__CYGWIN__)
#include 
#include 
#else  // WIN32 check
#include 
#include 
#include 
#include 
#include 
#endif  // WIN32 check

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "httpserver/string_utilities.hpp"

#pragma GCC diagnostic ignored "-Warray-bounds"
#define CHECK_BIT(var, pos) ((var) & (1 sin6_addr), to_ret, INET6_ADDRSTRLEN);
        return to_ret;
    } else if (AF_INET == sa->sa_family) {
        inet_ntop(AF_INET, &((reinterpret_cast(sa))->sin_addr), to_ret, INET_ADDRSTRLEN);
        return to_ret;
    } else {
        throw std::invalid_argument("IP family must be either AF_INET or AF_INET6");
    }
}

uint16_t get_port(const struct sockaddr* sa) {
    if (!sa) throw std::invalid_argument("socket pointer is null");

    if (sa->sa_family == AF_INET) {
        return (reinterpret_cast(sa))->sin_port;
    } else if (sa->sa_family == AF_INET6) {
        return (reinterpret_cast(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;

    unsigned int rpos = 0;
    unsigned int wpos = 0;

    unsigned int num;
    unsigned int size = val->size();

    while (rpos < size && (*val)[rpos] != '\0') {
        switch ((*val)[rpos]) {
            case '+':
                (*val)[wpos] = ' ';
                wpos++;
                rpos++;
                break;
            case '%':
                if (size > rpos + 2 && ((1 == sscanf(val->substr(rpos + 1, 2).c_str(), "%2x", &num)) || (1 == sscanf(val->substr(rpos + 1, 2).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;
        const in_addr* sin_addr_pt = &((reinterpret_cast(ip))->sin_addr);
        for (int i = 0; i < 4; i++) {
            pieces[12 + i] = (reinterpret_cast(sin_addr_pt))[i];
        }
    } else {
        ip_version = http_utils::IPV6;
        const in6_addr* sin_addr6_pt = &((reinterpret_cast(ip))->sin6_addr);
        for (int i = 0; i < 16; i++) {
            pieces[i] = (reinterpret_cast(sin_addr6_pt))[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) {
                    std::stringstream ss;
                    ss 

Web Proxy Viewer  |  New URL  |  Original Page