geoipdb 0.4.3 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|