geoipdb 0.4.3 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +6 -0
- data/.jrubyrc +12 -0
- data/.rvmrc +1 -1
- data/Gemfile +2 -2
- data/README.markdown +2 -2
- data/Rakefile +4 -4
- data/ext/geoipdb/extconf.rb +1 -3
- data/ext/geoipdb/src/City.java +120 -0
- data/ext/geoipdb/src/CsvReader.java +29 -0
- data/ext/geoipdb/src/GeoIpDb.java +101 -0
- data/ext/geoipdb/src/IpRange.java +110 -0
- data/geoipdb.gemspec +3 -5
- data/lib/geoipdb.jar +0 -0
- data/lib/geoipdb.rb +6 -15
- data/lib/ip_information.rb +27 -0
- data/lib/jgeoipdb.rb +43 -0
- data/sample_data/cities.csv +1 -1
- data/sample_data/ip_ranges.csv +8 -8
- data/spec/geoipdb_spec.rb +26 -20
- data/tasks/compile.rake +8 -0
- metadata +36 -24
- data/VERSION +0 -1
data/.gitignore
CHANGED
data/.jrubyrc
ADDED
data/.rvmrc
CHANGED
@@ -1 +1 @@
|
|
1
|
-
rvm use --create
|
1
|
+
rvm use --create jruby-1.7.2@geoipdb
|
data/Gemfile
CHANGED
data/README.markdown
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# geoipdb: fast (in memory!) geo location db.
|
2
2
|
|
3
|
-
Fast (>3 Mio queries/sec!!!) GeoIpDb implementation for Ruby using C-Extensions.
|
3
|
+
Fast (>3 Mio queries/sec!!!) GeoIpDb implementation for Ruby using C/Java-Extensions.
|
4
4
|
|
5
5
|
* Returns a GeoLocation and additional information for a given IP.
|
6
6
|
* Reads Data from CSV-Files and uses internal binary caching.
|
@@ -15,4 +15,4 @@ Fast (>3 Mio queries/sec!!!) GeoIpDb implementation for Ruby using C-Extensions.
|
|
15
15
|
== Copyright
|
16
16
|
|
17
17
|
Copyright (c) 2010 madvertise GmbH. See LICENSE.txt for
|
18
|
-
further details.
|
18
|
+
further details.
|
data/Rakefile
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require "bundler/setup"
|
4
|
-
require "bundler/gem_tasks"
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'bundler/gem_tasks'
|
5
3
|
|
6
4
|
Dir['tasks/**/*.rake'].each { |t| load t }
|
7
5
|
|
8
6
|
task :default => [:spec]
|
7
|
+
task :build => :compile
|
8
|
+
task :spec => :compile
|
data/ext/geoipdb/extconf.rb
CHANGED
@@ -0,0 +1,120 @@
|
|
1
|
+
public class City implements Comparable<City>
|
2
|
+
{
|
3
|
+
int cityCode;
|
4
|
+
String name;
|
5
|
+
double lat;
|
6
|
+
double lng;
|
7
|
+
String countryISO3;
|
8
|
+
String countryISO2;
|
9
|
+
|
10
|
+
|
11
|
+
public static final String[] country_iso2_codes = {
|
12
|
+
"--", "ap", "eu", "ad", "ae", "af", "ag", "ai", "al", "am", "an", "ao",
|
13
|
+
"aq", "ar", "as", "at", "au", "aw", "az", "ba", "bb", "bd", "be", "bf",
|
14
|
+
"bg", "bh", "bi", "bj", "bm", "bn", "bo", "br", "bs", "bt", "bv", "bw",
|
15
|
+
"by", "bz", "ca", "cc", "cd", "cf", "cg", "ch", "ci", "ck", "cl", "cm",
|
16
|
+
"cn", "co", "cr", "cu", "cv", "cx", "cy", "cz", "de", "dj", "dk", "dm",
|
17
|
+
"do", "dz", "ec", "ee", "eg", "eh", "er", "es", "et", "fi", "fj", "fk",
|
18
|
+
"fm", "fo", "fr", "fx", "ga", "gb", "gd", "ge", "gf", "gh", "gi", "gl",
|
19
|
+
"gm", "gn", "gp", "gq", "gr", "gs", "gt", "gu", "gw", "gy", "hk", "hm",
|
20
|
+
"hn", "hr", "ht", "hu", "id", "ie", "il", "in", "io", "iq", "ir", "is",
|
21
|
+
"it", "jm", "jo", "jp", "ke", "kg", "kh", "ki", "km", "kn", "kp", "kr",
|
22
|
+
"kw", "ky", "kz", "la", "lb", "lc", "li", "lk", "lr", "ls", "lt", "lu",
|
23
|
+
"lv", "ly", "ma", "mc", "md", "mg", "mh", "mk", "ml", "mm", "mn", "mo",
|
24
|
+
"mp", "mq", "mr", "ms", "mt", "mu", "mv", "mw", "mx", "my", "mz", "na",
|
25
|
+
"nc", "ne", "nf", "ng", "ni", "nl", "no", "np", "nr", "nu", "nz", "om",
|
26
|
+
"pa", "pe", "pf", "pg", "ph", "pk", "pl", "pm", "pn", "pr", "ps", "pt",
|
27
|
+
"pw", "py", "qa", "re", "ro", "ru", "rw", "sa", "sb", "sc", "sd", "se",
|
28
|
+
"sg", "sh", "si", "sj", "sk", "sl", "sm", "sn", "so", "sr", "st", "sv",
|
29
|
+
"sy", "sz", "tc", "td", "tf", "tg", "th", "tj", "tk", "tm", "tn", "to",
|
30
|
+
"tl", "tr", "tt", "tv", "tw", "tz", "ua", "ug", "um", "us", "uy", "uz",
|
31
|
+
"va", "vc", "ve", "vg", "vi", "vn", "vu", "wf", "ws", "ye", "yt", "rs",
|
32
|
+
"za", "zm", "me", "zw", "a1", "a2", "o1", "ax", "gg", "im", "je", "bl",
|
33
|
+
"mf"
|
34
|
+
};
|
35
|
+
|
36
|
+
public static final String[] country_iso3_codes = {
|
37
|
+
"--", "ap", "eu", "and", "are", "afg", "atg", "aia", "alb", "arm",
|
38
|
+
"ant", "ago", "aq", "arg", "asm", "aut", "aus", "abw", "aze", "bih",
|
39
|
+
"brb", "bgd", "bel", "bfa", "bgr", "bhr", "bdi", "ben", "bmu", "brn",
|
40
|
+
"bol", "bra", "bhs", "btn", "bv", "bwa", "blr", "blz", "can", "cc",
|
41
|
+
"cod", "caf", "cog", "che", "civ", "cok", "chl", "cmr", "chn", "col",
|
42
|
+
"cri", "cub", "cpv", "cx", "cyp", "cze", "deu", "dji", "dnk", "dma",
|
43
|
+
"dom", "dza", "ecu", "est", "egy", "esh", "eri", "esp", "eth", "fin",
|
44
|
+
"fji", "flk", "fsm", "fro", "fra", "fx", "gab", "gbr", "grd", "geo",
|
45
|
+
"guf", "gha", "gib", "grl", "gmb", "gin", "glp", "gnq", "grc", "gs",
|
46
|
+
"gtm", "gum", "gnb", "guy", "hkg", "hm", "hnd", "hrv", "hti", "hun",
|
47
|
+
"idn", "irl", "isr", "ind", "io", "irq", "irn", "isl", "ita", "jam",
|
48
|
+
"jor", "jpn", "ken", "kgz", "khm", "kir", "com", "kna", "prk", "kor",
|
49
|
+
"kwt", "cym", "kaz", "lao", "lbn", "lca", "lie", "lka", "lbr", "lso",
|
50
|
+
"ltu", "lux", "lva", "lby", "mar", "mco", "mda", "mdg", "mhl", "mkd",
|
51
|
+
"mli", "mmr", "mng", "mac", "mnp", "mtq", "mrt", "msr", "mlt", "mus",
|
52
|
+
"mdv", "mwi", "mex", "mys", "moz", "nam", "ncl", "ner", "nfk", "nga",
|
53
|
+
"nic", "nld", "nor", "npl", "nru", "niu", "nzl", "omn", "pan", "per",
|
54
|
+
"pyf", "png", "phl", "pak", "pol", "spm", "pcn", "pri", "pse", "prt",
|
55
|
+
"plw", "pry", "qat", "reu", "rou", "rus", "rwa", "sau", "slb", "syc",
|
56
|
+
"sdn", "swe", "sgp", "shn", "svn", "sjm", "svk", "sle", "smr", "sen",
|
57
|
+
"som", "sur", "stp", "slv", "syr", "swz", "tca", "tcd", "tf", "tgo",
|
58
|
+
"tha", "tjk", "tkl", "tkm", "tun", "ton", "tls", "tur", "tto", "tuv",
|
59
|
+
"twn", "tza", "ukr", "uga", "um", "usa", "ury", "uzb", "vat", "vct",
|
60
|
+
"ven", "vgb", "vir", "vnm", "vut", "wlf", "wsm", "yem", "yt", "srb",
|
61
|
+
"zaf", "zmb", "mne", "zwe", "a1", "a2", "o1", "ala", "ggy", "imn",
|
62
|
+
"jey", "blm", "maf"
|
63
|
+
};
|
64
|
+
|
65
|
+
public City(String[] cityValues)
|
66
|
+
{
|
67
|
+
this.cityCode = Integer.parseInt(cityValues[4]);
|
68
|
+
this.name = cityValues[2];
|
69
|
+
this.countryISO2 = iso2_code(cityValues[0]);
|
70
|
+
this.countryISO3 = cityValues[0];
|
71
|
+
this.lat = Double.parseDouble(cityValues[5]);
|
72
|
+
this.lng = Double.parseDouble(cityValues[6]);
|
73
|
+
}
|
74
|
+
|
75
|
+
private String iso2_code(String iso3_code)
|
76
|
+
{
|
77
|
+
int index = 0;
|
78
|
+
for (index = 0; index < country_iso3_codes.length; index++) {
|
79
|
+
if (country_iso3_codes[index].equals(iso3_code)) {
|
80
|
+
return country_iso2_codes[index];
|
81
|
+
}
|
82
|
+
}
|
83
|
+
return country_iso2_codes[0];
|
84
|
+
}
|
85
|
+
|
86
|
+
@Override
|
87
|
+
public int compareTo(City other)
|
88
|
+
{
|
89
|
+
return this.cityCode - other.cityCode;
|
90
|
+
}
|
91
|
+
|
92
|
+
public int getCityCode()
|
93
|
+
{
|
94
|
+
return cityCode;
|
95
|
+
}
|
96
|
+
|
97
|
+
public String getName()
|
98
|
+
{
|
99
|
+
return name;
|
100
|
+
}
|
101
|
+
|
102
|
+
public double getLat()
|
103
|
+
{
|
104
|
+
return lat;
|
105
|
+
}
|
106
|
+
|
107
|
+
public double getLng() {
|
108
|
+
return lng;
|
109
|
+
}
|
110
|
+
|
111
|
+
public String getCountryISO3()
|
112
|
+
{
|
113
|
+
return countryISO3;
|
114
|
+
}
|
115
|
+
|
116
|
+
public String getCountryISO2()
|
117
|
+
{
|
118
|
+
return countryISO2;
|
119
|
+
}
|
120
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import java.io.BufferedReader;
|
2
|
+
import java.io.FileNotFoundException;
|
3
|
+
import java.io.FileReader;
|
4
|
+
import java.io.IOException;
|
5
|
+
|
6
|
+
public class CsvReader
|
7
|
+
{
|
8
|
+
private BufferedReader reader = null;
|
9
|
+
|
10
|
+
public CsvReader(String file_name) throws FileNotFoundException {
|
11
|
+
reader = new BufferedReader(new FileReader(file_name));
|
12
|
+
}
|
13
|
+
|
14
|
+
public String[] readLine()
|
15
|
+
{
|
16
|
+
try {
|
17
|
+
String line = "";
|
18
|
+
String[] token = null;
|
19
|
+
|
20
|
+
if ((line = reader.readLine()) != null) {
|
21
|
+
token = line.split(",");
|
22
|
+
}
|
23
|
+
|
24
|
+
return token;
|
25
|
+
} catch (IOException e) {
|
26
|
+
return null;
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
@@ -0,0 +1,101 @@
|
|
1
|
+
import java.io.FileNotFoundException;
|
2
|
+
import java.util.ArrayList;
|
3
|
+
import java.util.Collections;
|
4
|
+
import java.util.HashMap;
|
5
|
+
|
6
|
+
public class GeoIpDb
|
7
|
+
{
|
8
|
+
private static final int MAX_CITY_COUNT = 1000000;
|
9
|
+
private static final int MAX_RANGE_COUNT = 10000000;
|
10
|
+
|
11
|
+
HashMap<Integer, City> cities;
|
12
|
+
ArrayList<String> isps;
|
13
|
+
ArrayList<IpRange> ranges;
|
14
|
+
|
15
|
+
public GeoIpDb(String citiesFileName, String rangesFileName) throws FileNotFoundException
|
16
|
+
{
|
17
|
+
cities = new HashMap<Integer, City>();
|
18
|
+
isps = new ArrayList<String>();
|
19
|
+
ranges = new ArrayList<IpRange>();
|
20
|
+
|
21
|
+
readCitiesCSV(citiesFileName);
|
22
|
+
readRangesCSV(rangesFileName);
|
23
|
+
}
|
24
|
+
|
25
|
+
public IpRange findRangeForIp(String ip)
|
26
|
+
{
|
27
|
+
if (ranges.isEmpty()) {
|
28
|
+
System.out.println("ERROR: DB has no ranges data. Can not search!");
|
29
|
+
return null;
|
30
|
+
}
|
31
|
+
|
32
|
+
int index = 0;
|
33
|
+
IpRange search = new IpRange(ip, "0");
|
34
|
+
index = Collections.binarySearch(ranges, search);
|
35
|
+
if (index < 0)
|
36
|
+
return null;
|
37
|
+
|
38
|
+
return ranges.get(index);
|
39
|
+
}
|
40
|
+
|
41
|
+
public City findCityForIpRange(IpRange range)
|
42
|
+
{
|
43
|
+
if (range == null) {
|
44
|
+
System.out.println("Cannot find city for no given range, right?");
|
45
|
+
return null;
|
46
|
+
}
|
47
|
+
if (cities.isEmpty()) {
|
48
|
+
System.out.println("ERROR: DB has no city data. Can not search!");
|
49
|
+
return null;
|
50
|
+
}
|
51
|
+
|
52
|
+
if (range.cityCode == 0) {
|
53
|
+
System.out.format("ERROR: Could not find city with index: %d\n", range.cityCode);
|
54
|
+
}
|
55
|
+
|
56
|
+
return cities.get(range.cityCode);
|
57
|
+
}
|
58
|
+
|
59
|
+
public ArrayList<IpRange> get_ranges()
|
60
|
+
{
|
61
|
+
return ranges;
|
62
|
+
}
|
63
|
+
|
64
|
+
private void readCitiesCSV(String file_name) throws FileNotFoundException
|
65
|
+
{
|
66
|
+
CsvReader reader = new CsvReader(file_name);
|
67
|
+
String[] line = null;
|
68
|
+
City city = null;
|
69
|
+
|
70
|
+
reader.readLine(); // skip first line
|
71
|
+
|
72
|
+
while ((line = reader.readLine()) != null) {
|
73
|
+
if (cities.size() >= MAX_CITY_COUNT){
|
74
|
+
System.out.format("ERROR: MAX_CITY_COUNT = %d limit reached - mek it bigger :-(\n", MAX_CITY_COUNT);
|
75
|
+
return;
|
76
|
+
}
|
77
|
+
city = new City(line);
|
78
|
+
cities.put(city.cityCode, city);
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
private void readRangesCSV(String file_name) throws FileNotFoundException
|
83
|
+
{
|
84
|
+
CsvReader reader = new CsvReader(file_name);
|
85
|
+
String[] line = null;
|
86
|
+
|
87
|
+
reader.readLine(); // skip first line
|
88
|
+
|
89
|
+
while ((line = reader.readLine()) != null) {
|
90
|
+
if (line.length < 5)
|
91
|
+
continue;
|
92
|
+
|
93
|
+
if (ranges.size() >= MAX_RANGE_COUNT){
|
94
|
+
System.out.format("ERROR: MAX_RANGE_COUNT = %d limit reached - mek it bigger :-(\n", MAX_RANGE_COUNT);
|
95
|
+
return;
|
96
|
+
}
|
97
|
+
|
98
|
+
ranges.add(new IpRange(line));
|
99
|
+
}
|
100
|
+
}
|
101
|
+
}
|
@@ -0,0 +1,110 @@
|
|
1
|
+
public class IpRange implements Comparable<IpRange>
|
2
|
+
{
|
3
|
+
long from;
|
4
|
+
long to;
|
5
|
+
boolean isMobile;
|
6
|
+
int cityCode;
|
7
|
+
String ispName;
|
8
|
+
|
9
|
+
public IpRange(String[] rangeValues)
|
10
|
+
{
|
11
|
+
this.from = ipToLong(rangeValues[0]);
|
12
|
+
this.to = ipToLong(rangeValues[1]);
|
13
|
+
this.isMobile = conTypeToBool(rangeValues[2]);
|
14
|
+
this.cityCode = Integer.parseInt(rangeValues[3]);
|
15
|
+
|
16
|
+
if (!rangeValues[4].equals("?")) {
|
17
|
+
// Use only the first 100 chars to be compliant with the c implementation
|
18
|
+
this.ispName = rangeValues[4].length() > 100 ? rangeValues[4].substring(0, 100) : rangeValues[4];
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
public IpRange(String from, String to)
|
23
|
+
{
|
24
|
+
this.from = ipToLong(from);
|
25
|
+
this.to = ipToLong(to);
|
26
|
+
}
|
27
|
+
|
28
|
+
public int getCityCode()
|
29
|
+
{
|
30
|
+
return cityCode;
|
31
|
+
}
|
32
|
+
|
33
|
+
public void setCityCode(int cityCode)
|
34
|
+
{
|
35
|
+
this.cityCode = cityCode;
|
36
|
+
}
|
37
|
+
|
38
|
+
public long getFrom()
|
39
|
+
{
|
40
|
+
return from;
|
41
|
+
}
|
42
|
+
|
43
|
+
public long getTo()
|
44
|
+
{
|
45
|
+
return to;
|
46
|
+
}
|
47
|
+
|
48
|
+
public boolean getIsMobile()
|
49
|
+
{
|
50
|
+
return isMobile;
|
51
|
+
}
|
52
|
+
|
53
|
+
public String getIspName()
|
54
|
+
{
|
55
|
+
return ispName;
|
56
|
+
}
|
57
|
+
|
58
|
+
private boolean conTypeToBool(String conType)
|
59
|
+
{
|
60
|
+
return (conType.length() > 0) && (conType.charAt(0) == 'm');
|
61
|
+
}
|
62
|
+
|
63
|
+
private long ipToLong(String ip)
|
64
|
+
{
|
65
|
+
long result = 0;
|
66
|
+
|
67
|
+
if (!(ip == null || ip.equals(""))) {
|
68
|
+
for (String octet : ip.split("\\.")) {
|
69
|
+
result = (result << 8) | Integer.parseInt(octet);
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
return result;
|
74
|
+
}
|
75
|
+
|
76
|
+
@Override
|
77
|
+
public int compareTo(IpRange other)
|
78
|
+
{
|
79
|
+
if (other == null) {
|
80
|
+
return 0;
|
81
|
+
}
|
82
|
+
|
83
|
+
if (other.from > 0 && other.to > 0 && this.from > 0 && this.to > 0) {
|
84
|
+
if (other.from < this.from)
|
85
|
+
return 1;
|
86
|
+
else if (other.from > this.to)
|
87
|
+
return -1;
|
88
|
+
else
|
89
|
+
return 0;
|
90
|
+
} else if (other.to == 0 && this.to > 0) {
|
91
|
+
if (other.from < this.from)
|
92
|
+
return 1;
|
93
|
+
else if (other.from > this.to)
|
94
|
+
return -1;
|
95
|
+
else
|
96
|
+
return 0;
|
97
|
+
} else if (this.to == 0 && other.to > 0) {
|
98
|
+
if (this.from < other.from)
|
99
|
+
return 1;
|
100
|
+
else if (this.from > other.from)
|
101
|
+
return -1;
|
102
|
+
else
|
103
|
+
return 0;
|
104
|
+
} else if (other.to == 0 && this.to == 0) {
|
105
|
+
return (int)(other.from - this.from);
|
106
|
+
}
|
107
|
+
|
108
|
+
return 0;
|
109
|
+
}
|
110
|
+
}
|
data/geoipdb.gemspec
CHANGED
@@ -2,18 +2,16 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |gem|
|
4
4
|
gem.name = "geoipdb"
|
5
|
-
gem.version = "0.
|
5
|
+
gem.version = "0.5.2"
|
6
6
|
gem.licenses = ["MIT"]
|
7
7
|
|
8
|
-
gem.authors = ["Eugen Martin", "Martin Karlsch"]
|
9
|
-
gem.email = ["eugeniusmartinus@googlemail.com", "martin.karlsch@madvertise.com"]
|
8
|
+
gem.authors = ["Eugen Martin", "Martin Karlsch", "Thomas Hirsch", "Benedikt Böhm"]
|
9
|
+
gem.email = ["eugeniusmartinus@googlemail.com", "martin.karlsch@madvertise.com", "thomas.hirsch@madvertise.com", "benedikt.boehm@madvertise.com"]
|
10
10
|
|
11
11
|
gem.description = "Returns a GeoLocation and additional information for given IP. Reads Data from CSV-Files and uses internal binary caching."
|
12
12
|
gem.summary = "Fast (>3 Mio queries/sec!!!) GeoIpDb implementation for Ruby using C-Extensions."
|
13
13
|
gem.homepage = "http://github.com/madvertise/geoipdb"
|
14
14
|
|
15
|
-
gem.extensions = ["ext/geoipdb/extconf.rb"]
|
16
|
-
|
17
15
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
16
|
gem.files = `git ls-files`.split("\n")
|
19
17
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
data/lib/geoipdb.jar
ADDED
Binary file
|
data/lib/geoipdb.rb
CHANGED
@@ -1,17 +1,8 @@
|
|
1
|
-
require '
|
1
|
+
require 'ip_information'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
attr_accessor :city_name
|
9
|
-
attr_accessor :lat
|
10
|
-
attr_accessor :lng
|
11
|
-
attr_accessor :is_mobile
|
12
|
-
attr_accessor :isp_name
|
13
|
-
|
14
|
-
def mobile?
|
15
|
-
@is_mobile
|
16
|
-
end
|
3
|
+
if defined?(JRUBY_VERSION)
|
4
|
+
require 'jgeoipdb'
|
5
|
+
require 'rbconfig'
|
6
|
+
else
|
7
|
+
require 'geoipdb/geoipdb'
|
17
8
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class IpInformation
|
2
|
+
|
3
|
+
ATTRIBS = [
|
4
|
+
:country_iso_code,
|
5
|
+
:city_code,
|
6
|
+
:city_name,
|
7
|
+
:lat,
|
8
|
+
:lng,
|
9
|
+
:is_mobile,
|
10
|
+
:isp_name,
|
11
|
+
]
|
12
|
+
|
13
|
+
ATTRIBS.each do |attrib|
|
14
|
+
attr_accessor attrib
|
15
|
+
end
|
16
|
+
|
17
|
+
def mobile?
|
18
|
+
@is_mobile
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_h
|
22
|
+
Hash[ATTRIBS.map do |attrib|
|
23
|
+
[attrib, send(attrib)]
|
24
|
+
end]
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
data/lib/jgeoipdb.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'java'
|
2
|
+
require File.expand_path('../geoipdb.jar', __FILE__)
|
3
|
+
|
4
|
+
class GeoIpDb
|
5
|
+
|
6
|
+
def self.init(cities_file, ranges_file, cache_file)
|
7
|
+
self.new(cities_file, ranges_file, cache_file)
|
8
|
+
rescue java.io.FileNotFoundException => e
|
9
|
+
return nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(cities_file, ranges_file, cache_file)
|
13
|
+
# the Java implementation does not support cache files,
|
14
|
+
# since the java serialisation is slower than the actual csv parsing
|
15
|
+
@jdb = Java::GeoIpDb.new(cities_file, ranges_file)
|
16
|
+
end
|
17
|
+
|
18
|
+
def information_for_ip(ip)
|
19
|
+
range = @jdb.find_range_for_ip(ip)
|
20
|
+
return nil unless range
|
21
|
+
|
22
|
+
city = @jdb.find_city_for_ip_range(range)
|
23
|
+
return nil unless city
|
24
|
+
|
25
|
+
isp = range.isp_name
|
26
|
+
build_ip_information_object(range, city, isp)
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_ip_information_object(range, city, isp)
|
30
|
+
info = IpInformation.new
|
31
|
+
|
32
|
+
info.country_iso_code = city.country_iso2
|
33
|
+
info.city_name = city.name
|
34
|
+
info.city_code = city.city_code
|
35
|
+
info.lng = city.lng
|
36
|
+
info.lat = city.lat
|
37
|
+
info.is_mobile = range.is_mobile
|
38
|
+
info.isp_name = isp && isp.to_sym
|
39
|
+
|
40
|
+
info
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
data/sample_data/cities.csv
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
COUNTRY,REGION,CITY-NAME,METRO-CODE,CITY-CODE,LATITUDE,LONGITUDE
|
2
2
|
***,***,?,0,7,0,0
|
3
3
|
afg,?,?,0,1,33,1
|
4
|
-
afg,no region,herat,-1,2,34.3452,62.
|
4
|
+
afg,no region,herat,-1,2,34.3452,62.12
|
5
5
|
afg,no region,kabul,-1,3,34.5167,69.1833
|
6
6
|
afg,no region,kandahar,-1,4,31.6111,65.702
|
7
7
|
afg,no region,mazar-e sharif,-1,5,36.7041,67.1096
|
data/sample_data/ip_ranges.csv
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
start_ip,end_ip,
|
2
|
-
0.0.0.0,0.0.0.255,mobile,0
|
1
|
+
start_ip,end_ip,connection_type,city_code,isp_name
|
2
|
+
0.0.0.0,0.0.0.255,mobile,0,?
|
3
3
|
0.0.1.0,0.255.255.255,mobile,1,asdf,
|
4
4
|
1.0.0.0,1.0.0.255,xdsl,2,vodafone
|
5
|
-
1.0.1.0,1.1.0.255,wireless,3
|
5
|
+
1.0.1.0,1.1.0.255,wireless,3,?
|
6
6
|
1.1.1.0,1.1.1.255,mobile,4,1vodafone2vodafone3vodafone4vodafone5vodafone1vodafone2vodafone3vodafone4vodafone5vodafone1vodafone2vodafone3vodafone4vodafone5vodafone1vodafone2vodafone3vodafone4vodafone5vodafone
|
7
|
-
1.1.2.0,1.2.2.255,mobile,5
|
8
|
-
1.2.3.0,1.2.3.255,mobile,5
|
9
|
-
1.2.4.0,1.3.255.255,mobile,2
|
10
|
-
1.4.0.0,1.4.0.255,mobile,5
|
11
|
-
1.4.1.0,1.8.255.255,mobile,3
|
7
|
+
1.1.2.0,1.2.2.255,mobile,5,?
|
8
|
+
1.2.3.0,1.2.3.255,mobile,5,?
|
9
|
+
1.2.4.0,1.3.255.255,mobile,2,?
|
10
|
+
1.4.0.0,1.4.0.255,mobile,5,?
|
11
|
+
1.4.1.0,1.8.255.255,mobile,3,?
|
data/spec/geoipdb_spec.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__)+'/spec_helper')
|
2
2
|
|
3
3
|
|
4
|
-
describe GeoIpDb do
|
5
|
-
|
4
|
+
describe GeoIpDb do
|
5
|
+
|
6
6
|
CACHE_FILE = 'sample_data/ipdb.cache'
|
7
|
-
|
7
|
+
|
8
8
|
def init_db
|
9
|
-
@db = GeoIpDb.init './sample_data/cities.csv', './sample_data/ip_ranges.csv', CACHE_FILE
|
10
|
-
end
|
11
|
-
|
9
|
+
@db = GeoIpDb.init './sample_data/cities.csv', './sample_data/ip_ranges.csv', CACHE_FILE
|
10
|
+
end
|
11
|
+
|
12
12
|
it "should not throw an exception fault if data is corrupt" do
|
13
13
|
@db = GeoIpDb.init './sample_data/cities_corrupt.csv', './sample_data/ip_ranges_corrupt.csv', CACHE_FILE
|
14
14
|
end
|
@@ -16,40 +16,46 @@ describe GeoIpDb do
|
|
16
16
|
it "should not init a db object if data files are missing" do
|
17
17
|
GeoIpDb.init( './sample_data/bla.csv', './sample_data/blubb.csv', CACHE_FILE ).should be_nil
|
18
18
|
end
|
19
|
-
|
20
|
-
it "should init correctly with sample data
|
19
|
+
|
20
|
+
it "should init correctly with sample data" do
|
21
21
|
init_db
|
22
22
|
@db.should_not be_nil
|
23
|
-
File.exist?(CACHE_FILE).should be_true
|
24
23
|
end
|
25
|
-
|
26
|
-
|
24
|
+
|
25
|
+
unless defined? JRUBY_VERSION
|
26
|
+
it "initializes cache_file correctly with sample data" do
|
27
|
+
init_db
|
28
|
+
File.exist?(CACHE_FILE).should be_true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "sould find the sample cities correcty" do
|
27
33
|
init_db
|
28
34
|
#afg,no region,kabul,-1,3,34.5167,69.1833
|
29
|
-
info = @db.information_for_ip "1.1.0.254"
|
35
|
+
info = @db.information_for_ip "1.1.0.254"
|
30
36
|
info.city_code.should == 3
|
31
|
-
info.city_name.should == 'kabul'
|
37
|
+
info.city_name.should == 'kabul'
|
32
38
|
info.country_iso_code.should == 'af'
|
33
39
|
info.lat.should == 34.5167
|
34
40
|
info.lng.should == 69.1833
|
35
41
|
info.should_not be_mobile
|
36
42
|
end
|
37
|
-
|
43
|
+
|
38
44
|
it 'should return correct is_mobile information' do
|
39
|
-
init_db
|
40
|
-
@db.information_for_ip("1.0.0.1").should_not be_mobile
|
45
|
+
init_db
|
46
|
+
@db.information_for_ip("1.0.0.1").should_not be_mobile
|
41
47
|
@db.information_for_ip("1.1.1.1").should be_mobile
|
42
|
-
end
|
43
|
-
|
48
|
+
end
|
49
|
+
|
44
50
|
it 'should return correct isp_name in ip_information' do
|
45
|
-
init_db
|
51
|
+
init_db
|
46
52
|
@db.information_for_ip("1.0.0.1").isp_name.should == :vodafone
|
47
53
|
@db.information_for_ip("1.1.1.1").isp_name.should == "1vodafone2vodafone3vodafone4vodafone5vodafone1vodafone2vodafone3vodafone4vodafone5vodafone1vodafone2vodafone3vodafone4vodafone5vodafone1vodafone2vodafone3vodafone4vodafone5vodafone"[0..99].to_sym
|
48
54
|
@db.information_for_ip("1.2.1.1").isp_name.should == nil
|
49
55
|
end
|
50
56
|
|
51
57
|
it "should write and read the cachefile correctly"
|
52
|
-
|
58
|
+
|
53
59
|
after :each do
|
54
60
|
File.unlink CACHE_FILE if File.exist? CACHE_FILE
|
55
61
|
end
|
data/tasks/compile.rake
ADDED
metadata
CHANGED
@@ -1,80 +1,92 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: geoipdb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.5.2
|
5
|
+
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Eugen Martin
|
9
9
|
- Martin Karlsch
|
10
|
-
|
10
|
+
- Thomas Hirsch
|
11
|
+
- Benedikt Böhm
|
12
|
+
autorequire:
|
11
13
|
bindir: bin
|
12
14
|
cert_chain: []
|
13
|
-
date:
|
15
|
+
date: 2013-01-10 00:00:00.000000000 Z
|
14
16
|
dependencies: []
|
15
|
-
description: Returns a GeoLocation and additional information for given IP. Reads
|
16
|
-
Data from CSV-Files and uses internal binary caching.
|
17
|
+
description: Returns a GeoLocation and additional information for given IP. Reads Data from CSV-Files and uses internal binary caching.
|
17
18
|
email:
|
18
19
|
- eugeniusmartinus@googlemail.com
|
19
20
|
- martin.karlsch@madvertise.com
|
21
|
+
- thomas.hirsch@madvertise.com
|
22
|
+
- benedikt.boehm@madvertise.com
|
20
23
|
executables: []
|
21
|
-
extensions:
|
22
|
-
- ext/geoipdb/extconf.rb
|
24
|
+
extensions: []
|
23
25
|
extra_rdoc_files: []
|
24
26
|
files:
|
25
|
-
- .document
|
26
|
-
- .gitignore
|
27
|
-
- .
|
28
|
-
- .
|
27
|
+
- ".document"
|
28
|
+
- ".gitignore"
|
29
|
+
- ".jrubyrc"
|
30
|
+
- ".rspec"
|
31
|
+
- ".rvmrc"
|
29
32
|
- Gemfile
|
30
33
|
- LICENSE.txt
|
31
34
|
- README.markdown
|
32
35
|
- Rakefile
|
33
|
-
- VERSION
|
34
36
|
- ext/geoipdb/extconf.rb
|
35
37
|
- ext/geoipdb/geoipdb.c
|
36
38
|
- ext/geoipdb/ipdb.c
|
37
39
|
- ext/geoipdb/ipdb.h
|
40
|
+
- ext/geoipdb/src/City.java
|
41
|
+
- ext/geoipdb/src/CsvReader.java
|
42
|
+
- ext/geoipdb/src/GeoIpDb.java
|
43
|
+
- ext/geoipdb/src/IpRange.java
|
38
44
|
- geoipdb.gemspec
|
45
|
+
- lib/geoipdb.jar
|
39
46
|
- lib/geoipdb.rb
|
47
|
+
- lib/ip_information.rb
|
48
|
+
- lib/jgeoipdb.rb
|
40
49
|
- sample_data/cities.csv
|
41
50
|
- sample_data/citiess_corrupt.csv
|
42
51
|
- sample_data/ip_ranges.csv
|
43
52
|
- sample_data/ip_ranges_corrupt.csv
|
44
53
|
- spec/geoipdb_spec.rb
|
45
54
|
- spec/spec_helper.rb
|
55
|
+
- tasks/compile.rake
|
46
56
|
- tasks/rspec.rake
|
47
57
|
- tasks/yard.rake
|
48
58
|
homepage: http://github.com/madvertise/geoipdb
|
49
59
|
licenses:
|
50
60
|
- MIT
|
51
|
-
post_install_message:
|
61
|
+
post_install_message:
|
52
62
|
rdoc_options: []
|
53
63
|
require_paths:
|
54
64
|
- lib
|
55
65
|
- ext
|
56
66
|
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
67
|
requirements:
|
59
|
-
- -
|
68
|
+
- - ">="
|
60
69
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
70
|
segments:
|
63
71
|
- 0
|
64
|
-
|
65
|
-
|
72
|
+
version: !binary |-
|
73
|
+
MA==
|
74
|
+
hash: 2
|
66
75
|
none: false
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
77
|
requirements:
|
68
|
-
- -
|
78
|
+
- - ">="
|
69
79
|
- !ruby/object:Gem::Version
|
70
|
-
version:
|
80
|
+
version: !binary |-
|
81
|
+
MA==
|
82
|
+
none: false
|
71
83
|
requirements: []
|
72
|
-
rubyforge_project:
|
84
|
+
rubyforge_project:
|
73
85
|
rubygems_version: 1.8.24
|
74
|
-
signing_key:
|
86
|
+
signing_key:
|
75
87
|
specification_version: 3
|
76
88
|
summary: Fast (>3 Mio queries/sec!!!) GeoIpDb implementation for Ruby using C-Extensions.
|
77
89
|
test_files:
|
78
90
|
- spec/geoipdb_spec.rb
|
79
91
|
- spec/spec_helper.rb
|
80
|
-
has_rdoc:
|
92
|
+
has_rdoc:
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.4.2
|