Created
July 16, 2011 15:32
-
-
Save markusl/1086449 to your computer and use it in GitHub Desktop.
C++ class to map IP addresses to countries using database from http://software77.net/geo-ip/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string> | |
#include <fstream> | |
#include <vector> | |
#include <sstream> | |
#include <algorithm> | |
#include <stdexcept> | |
std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) { | |
std::stringstream ss(s); | |
std::string item; | |
while(std::getline(ss, item, delim)) { | |
elems.push_back(item); | |
} | |
return elems; | |
} | |
std::vector<std::string> split(const std::string &s, char delim) { | |
std::vector<std::string> elems; | |
return split(s, delim, elems); | |
} | |
template <class T> | |
T stringTo(const std::string &str) | |
{ | |
T result; | |
std::stringstream ss(str); | |
ss >> result; | |
return result; | |
} | |
template <class Ty, class Container> | |
std::vector<Ty> convertContainerTo(const Container &source) | |
{ | |
std::vector<Ty> result; | |
std::for_each(source.begin(), source.end(), | |
[&result](const std::string &it){ result.push_back(stringTo<Ty>(it)); }); | |
return result; | |
} | |
typedef unsigned int uint32_t; | |
typedef uint32_t IpAddress_t; | |
/** IP address mapping entry */ | |
class IpAddressMapping { | |
public: | |
std::string country; | |
IpAddress_t startAddress; | |
}; | |
/** Class for mapping IP addresses to countries using database | |
* from http://software77.net/geo-ip/ */ | |
class IpToCountrySlow | |
{ | |
std::vector<IpAddressMapping> m_countryIpList; | |
public: | |
/** Construct new IP-to-country mapper from the specified file. */ | |
IpToCountrySlow(const std::string &FileName = "IpToCountry.csv") | |
{ | |
std::ifstream file(FileName); | |
while(file.good() && !file.eof()) | |
{ | |
std::string line; | |
std::getline(file, line); | |
if(line.find_first_of('#') == std::string::npos && line.length() > 0) | |
m_countryIpList.push_back(ParseSingleLine(line)); | |
} | |
} | |
/** Find the country for given IP address or throw std::exception. */ | |
IpAddressMapping GetCountry(const std::string &address) const | |
{ | |
IpAddress_t integerIp = IntegerFromIp(address); | |
auto it = std::find_if(m_countryIpList.rbegin(), m_countryIpList.rend(), | |
[integerIp](IpAddressMapping it) { return it.startAddress <= integerIp; }); | |
if(it == m_countryIpList.rend()) | |
throw std::runtime_error("Address not found"); | |
return *it; | |
} | |
/** Convert a human-readable ipv4 address to integer */ | |
static IpAddress_t IntegerFromIp(const std::string &ip) | |
{ | |
auto tokens = split(ip, '.'); | |
auto integers = convertContainerTo<uint32_t>(tokens); | |
return (integers[0] << (3*8)) + | |
(integers[1] << (2*8)) + | |
(integers[2] << (1*8)) + | |
integers[3]; | |
} | |
private: | |
// File format: | |
// "1464729600","1464860671","ripencc","1117497600","DE","DEU","Germany" | |
static IpAddressMapping ParseSingleLine(const std::string &line) | |
{ | |
IpAddressMapping mapping; | |
auto tokens = split(line, ','); | |
mapping.country = tokens[6].substr(1, tokens[6].length()-2); | |
mapping.startAddress = stringTo<uint32_t>(tokens[0].substr(1, tokens[0].length()-2)); | |
return mapping; | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Example usage | |
int main() | |
{ | |
IpToCountrySlow iptc; | |
IpAddressMapping country = iptc.GetCountry("158.127.18.60"); | |
} |
I have try it but nothing happened,what is the expected result??
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How do I compile this please?