geoip 1.1.2 → 1.2.0
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/History.rdoc +4 -0
- data/README.rdoc +20 -11
- data/Rakefile +1 -1
- data/geoip.gemspec +4 -4
- data/lib/geoip.rb +50 -16
- metadata +4 -4
data/History.rdoc
CHANGED
data/README.rdoc
CHANGED
@@ -13,6 +13,11 @@ and the city, ISP and other information, if you have that database version.
|
|
13
13
|
Includes support for ASN data files, thanks to Roland Matiz.
|
14
14
|
This release adds support for timezone names, thanks to Tonni Aagesen.
|
15
15
|
|
16
|
+
If you have required 'io/extra' and have IO#pread, cross-process file-descriptor sharing is enabled.
|
17
|
+
Each GeoIP instance keeps the file descriptor open, with a Mutex for thread-safety.
|
18
|
+
You should consider this if your process will fork without exec, as
|
19
|
+
{modrails does}[http://www.modrails.com/documentation/Users%20guide%20Nginx.html#_smart_spawning_gotcha_1_unintential_file_descriptor_sharing]
|
20
|
+
|
16
21
|
== SYNOPSIS:
|
17
22
|
|
18
23
|
require 'geoip'
|
@@ -25,9 +30,9 @@ This release adds support for timezone names, thanks to Tonni Aagesen.
|
|
25
30
|
c.to_hash
|
26
31
|
=> {:country_code3=>"FIN", :country_name=>"Finland", :continent_code=>"EU", :request=>"www.nokia.com", :country_code=>69, :country_code2=>"FI", :ip=>"147.243.3.83"}
|
27
32
|
|
28
|
-
|
29
|
-
|
30
|
-
|
33
|
+
Returned values are the requested hostname, the IP address as a dotted quad,
|
34
|
+
Maxmind's country code, the ISO3166-1 alpha-2 country code, the ISO3166-2 alpha-3
|
35
|
+
country code, the ISO3166 country name, and the continent code.
|
31
36
|
|
32
37
|
# Use the city database:
|
33
38
|
c = GeoIP.new('GeoLiteCity.dat').city('github.com')
|
@@ -40,15 +45,19 @@ This release adds support for timezone names, thanks to Tonni Aagesen.
|
|
40
45
|
GeoIP.new('GeoCity.dat').city('github.com')
|
41
46
|
=> ["github.com", "207.97.227.239", "US", "USA", "United States", "NA", "CA", "San Francisco", "94110", 37.7484, -122.4156, 807, 415, "America/Los_Angeles"]
|
42
47
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
+
# Use the city ipv6 database:
|
49
|
+
GeoIP.new('GeoLiteCityv6.dat').city('::151.38.39.114')
|
50
|
+
=> ["::151.38.39.114", "::151.38.39.114", "IT", "ITA", "Italy", "EU", "05", "Piacenza", "", 45.016699999999986, 9.666699999999992, nil, nil, "Europe/Rome"]
|
51
|
+
|
52
|
+
Returned values are the requested hostname, the IP address as a dotted quad,
|
53
|
+
the ISO3166-1 alpha-2 country code, the ISO3166-2 alpha-3 country code, the
|
54
|
+
ISO3166 country name, the continent code, the region (state or territory) name,
|
55
|
+
city name, postal_code/zipcode, latitude, longitude, USA DMA code, USA area code,
|
56
|
+
timezone name.
|
48
57
|
|
49
|
-
|
50
|
-
|
51
|
-
|
58
|
+
Result arrays from both city and country have mixed-in accessor methods as appropriate:
|
59
|
+
request, ip, country_code, country_code2, country_code3, country_name, continent_code,
|
60
|
+
region_name, city_name, postal_code, latitude, longitude, dma_code, area_code, timezone
|
52
61
|
|
53
62
|
GeoIP.new('GeoIPASNum.dat').asn("www.fsb.ru")
|
54
63
|
=> ["AS8342", "RTComm.RU Autonomous System"]
|
data/Rakefile
CHANGED
@@ -9,7 +9,7 @@ Jeweler::Tasks.new do |gem|
|
|
9
9
|
gem.name = "geoip"
|
10
10
|
gem.version = GeoIP::VERSION
|
11
11
|
gem.homepage = "http://github.com/cjheath/geoip"
|
12
|
-
gem.license = "
|
12
|
+
gem.license = "GPL"
|
13
13
|
gem.summary = %Q{GeoIP searches a GeoIP database for a given host or IP address, and returns information about the country where the IP address is allocated, and the city, ISP and other information, if you have that database version.}
|
14
14
|
gem.description = %Q{GeoIP searches a GeoIP database for a given host or IP address, and
|
15
15
|
returns information about the country where the IP address is allocated,
|
data/geoip.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "geoip"
|
8
|
-
s.version = "1.
|
8
|
+
s.version = "1.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Clifford Heath", "Roland Moriz"]
|
12
|
-
s.date = "2012-
|
12
|
+
s.date = "2012-10-16"
|
13
13
|
s.description = "GeoIP searches a GeoIP database for a given host or IP address, and\nreturns information about the country where the IP address is allocated,\nand the city, ISP and other information, if you have that database version."
|
14
14
|
s.email = ["clifford.heath@gmail.com", "rmoriz@gmail.com"]
|
15
15
|
s.executables = ["geoip"]
|
@@ -40,9 +40,9 @@ Gem::Specification.new do |s|
|
|
40
40
|
"website/template.rhtml"
|
41
41
|
]
|
42
42
|
s.homepage = "http://github.com/cjheath/geoip"
|
43
|
-
s.licenses = ["
|
43
|
+
s.licenses = ["GPL"]
|
44
44
|
s.require_paths = ["lib"]
|
45
|
-
s.rubygems_version = "1.8.
|
45
|
+
s.rubygems_version = "1.8.24"
|
46
46
|
s.summary = "GeoIP searches a GeoIP database for a given host or IP address, and returns information about the country where the IP address is allocated, and the city, ISP and other information, if you have that database version."
|
47
47
|
|
48
48
|
if s.respond_to? :specification_version then
|
data/lib/geoip.rb
CHANGED
@@ -48,13 +48,18 @@ begin
|
|
48
48
|
rescue LoadError
|
49
49
|
# oh well, hope they're not forking after initializing
|
50
50
|
end
|
51
|
+
begin
|
52
|
+
require 'ipaddr' # Needed for IPv6 support
|
53
|
+
rescue LoadError
|
54
|
+
# Won't work for an IPv6 database
|
55
|
+
end
|
51
56
|
|
52
57
|
require 'yaml'
|
53
58
|
|
54
59
|
class GeoIP
|
55
60
|
|
56
61
|
# The GeoIP GEM version number
|
57
|
-
VERSION = "1.
|
62
|
+
VERSION = "1.2.0"
|
58
63
|
|
59
64
|
# The +data/+ directory for geoip
|
60
65
|
DATA_DIR = File.expand_path(File.join(File.dirname(__FILE__),'..','data','geoip'))
|
@@ -87,6 +92,7 @@ class GeoIP
|
|
87
92
|
GEOIP_PROXY_EDITION = 8
|
88
93
|
GEOIP_ASNUM_EDITION = 9
|
89
94
|
GEOIP_NETSPEED_EDITION = 10
|
95
|
+
GEOIP_CITY_EDITION_REV1_V6 = 30
|
90
96
|
|
91
97
|
COUNTRY_BEGIN = 16776960 #:nodoc:
|
92
98
|
STATE_BEGIN_REV0 = 16700000 #:nodoc:
|
@@ -171,21 +177,21 @@ class GeoIP
|
|
171
177
|
#
|
172
178
|
def country(hostname)
|
173
179
|
if (@database_type == GEOIP_CITY_EDITION_REV0 ||
|
174
|
-
@database_type == GEOIP_CITY_EDITION_REV1
|
180
|
+
@database_type == GEOIP_CITY_EDITION_REV1 ||
|
181
|
+
@database_type == GEOIP_CITY_EDITION_REV1_V6)
|
175
182
|
return city(hostname)
|
176
183
|
end
|
177
184
|
|
178
|
-
ip = lookup_ip(hostname)
|
179
|
-
|
180
|
-
# Convert numeric IP address to an integer
|
181
|
-
ipnum = iptonum(ip)
|
182
|
-
|
183
185
|
if (@database_type != GEOIP_COUNTRY_EDITION &&
|
184
186
|
@database_type != GEOIP_PROXY_EDITION &&
|
185
187
|
@database_type != GEOIP_NETSPEED_EDITION)
|
186
188
|
throw "Invalid GeoIP database type, can't look up Country by IP"
|
187
189
|
end
|
188
190
|
|
191
|
+
ip = lookup_ip(hostname)
|
192
|
+
|
193
|
+
ipnum = iptonum(ip) # Convert numeric IP address to an integer
|
194
|
+
|
189
195
|
code = (seek_record(ipnum) - COUNTRY_BEGIN)
|
190
196
|
|
191
197
|
Country.new(
|
@@ -223,16 +229,18 @@ class GeoIP
|
|
223
229
|
def city(hostname)
|
224
230
|
ip = lookup_ip(hostname)
|
225
231
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
232
|
+
if (@database_type == GEOIP_CITY_EDITION_REV0 ||
|
233
|
+
@database_type == GEOIP_CITY_EDITION_REV1)
|
234
|
+
# Convert numeric IP address to an integer
|
235
|
+
ipnum = iptonum(ip)
|
236
|
+
pos = seek_record(ipnum)
|
237
|
+
elsif (@database_type == GEOIP_CITY_EDITION_REV1_V6)
|
238
|
+
ipaddr = IPAddr.new ip
|
239
|
+
pos = seek_record_v6(ipaddr.to_i)
|
240
|
+
else
|
231
241
|
throw "Invalid GeoIP database type, can't look up City by IP"
|
232
242
|
end
|
233
243
|
|
234
|
-
pos = seek_record(ipnum)
|
235
|
-
|
236
244
|
# This next statement was added to MaxMind's C version after it was
|
237
245
|
# rewritten in Ruby. It prevents unassigned IP addresses from returning
|
238
246
|
# bogus data. There was concern over whether the changes to an
|
@@ -361,6 +369,7 @@ class GeoIP
|
|
361
369
|
@database_segments = [STATE_BEGIN_REV1]
|
362
370
|
elsif (@database_type == GEOIP_CITY_EDITION_REV0 ||
|
363
371
|
@database_type == GEOIP_CITY_EDITION_REV1 ||
|
372
|
+
@database_type == GEOIP_CITY_EDITION_REV1_V6 ||
|
364
373
|
@database_type == GEOIP_ORG_EDITION ||
|
365
374
|
@database_type == GEOIP_ISP_EDITION ||
|
366
375
|
@database_type == GEOIP_ASNUM_EDITION)
|
@@ -487,9 +496,11 @@ class GeoIP
|
|
487
496
|
end
|
488
497
|
|
489
498
|
def lookup_ip(ip_or_hostname) # :nodoc:
|
490
|
-
|
499
|
+
if !ip_or_hostname.kind_of?(String) or ip_or_hostname =~ /^[0-9.]+$/
|
500
|
+
return ip_or_hostname
|
501
|
+
end
|
491
502
|
|
492
|
-
# Lookup IP address, we were given a name
|
503
|
+
# Lookup IP address, we were given a name or IPv6 address
|
493
504
|
ip = IPSocket.getaddress(ip_or_hostname)
|
494
505
|
ip = '0.0.0.0' if ip == '::1'
|
495
506
|
ip
|
@@ -528,6 +539,29 @@ class GeoIP
|
|
528
539
|
end
|
529
540
|
end
|
530
541
|
|
542
|
+
def seek_record_v6(ipnum)
|
543
|
+
|
544
|
+
# Binary search in the file.
|
545
|
+
# Records are pairs of little-endian integers, each of @record_length.
|
546
|
+
offset = 0
|
547
|
+
mask = 1 << 127
|
548
|
+
|
549
|
+
127.downto(0) do |depth|
|
550
|
+
off = (@record_length * 2 * offset)
|
551
|
+
buf = atomic_read(@record_length * 2, off)
|
552
|
+
|
553
|
+
buf.slice!(0...@record_length) if ((ipnum & mask) != 0)
|
554
|
+
offset = le_to_ui(buf[0...@record_length].unpack("C*"))
|
555
|
+
|
556
|
+
if (offset >= @database_segments[0])
|
557
|
+
return offset
|
558
|
+
end
|
559
|
+
|
560
|
+
mask >>= 1
|
561
|
+
end
|
562
|
+
|
563
|
+
end
|
564
|
+
|
531
565
|
# Convert a big-endian array of numeric bytes to unsigned int.
|
532
566
|
#
|
533
567
|
# Returns the unsigned Integer.
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: geoip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-10-16 00:00:00.000000000 Z
|
14
14
|
dependencies: []
|
15
15
|
description: ! 'GeoIP searches a GeoIP database for a given host or IP address, and
|
16
16
|
|
@@ -49,7 +49,7 @@ files:
|
|
49
49
|
- website/template.rhtml
|
50
50
|
homepage: http://github.com/cjheath/geoip
|
51
51
|
licenses:
|
52
|
-
-
|
52
|
+
- GPL
|
53
53
|
post_install_message:
|
54
54
|
rdoc_options: []
|
55
55
|
require_paths:
|
@@ -68,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
68
|
version: '0'
|
69
69
|
requirements: []
|
70
70
|
rubyforge_project:
|
71
|
-
rubygems_version: 1.8.
|
71
|
+
rubygems_version: 1.8.24
|
72
72
|
signing_key:
|
73
73
|
specification_version: 3
|
74
74
|
summary: GeoIP searches a GeoIP database for a given host or IP address, and returns
|