geoip 1.2.0 → 1.3.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/README.rdoc +10 -6
- data/Rakefile +2 -2
- data/data/geoip/region.yml +4249 -0
- data/geoip.gemspec +4 -3
- data/lib/geoip.rb +139 -21
- data/script/txt2html +4 -5
- data/website/index.txt +4 -4
- metadata +4 -3
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.3.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 = "
|
|
12
|
+
s.date = "2013-08-13"
|
|
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"]
|
|
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
|
|
|
26
26
|
"data/geoip/country_code3.yml",
|
|
27
27
|
"data/geoip/country_continent.yml",
|
|
28
28
|
"data/geoip/country_name.yml",
|
|
29
|
+
"data/geoip/region.yml",
|
|
29
30
|
"data/geoip/time_zone.yml",
|
|
30
31
|
"geoip.gemspec",
|
|
31
32
|
"lib/geoip.rb",
|
|
@@ -40,7 +41,7 @@ Gem::Specification.new do |s|
|
|
|
40
41
|
"website/template.rhtml"
|
|
41
42
|
]
|
|
42
43
|
s.homepage = "http://github.com/cjheath/geoip"
|
|
43
|
-
s.licenses = ["
|
|
44
|
+
s.licenses = ["LGPL"]
|
|
44
45
|
s.require_paths = ["lib"]
|
|
45
46
|
s.rubygems_version = "1.8.24"
|
|
46
47
|
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."
|
data/lib/geoip.rb
CHANGED
|
@@ -8,19 +8,18 @@
|
|
|
8
8
|
# Derived from the C version, Copyright (C) 2003 MaxMind LLC
|
|
9
9
|
#
|
|
10
10
|
# This library is free software; you can redistribute it and/or
|
|
11
|
-
# modify it under the terms of the GNU General Public
|
|
11
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
12
12
|
# License as published by the Free Software Foundation; either
|
|
13
13
|
# version 2.1 of the License, or (at your option) any later version.
|
|
14
14
|
#
|
|
15
15
|
# This library is distributed in the hope that it will be useful,
|
|
16
16
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
17
17
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
18
|
-
# General Public License for more details.
|
|
18
|
+
# Lesser General Public License for more details.
|
|
19
19
|
#
|
|
20
|
-
# You should have received a copy of the GNU General Public
|
|
20
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
21
21
|
# License along with this library; if not, write to the Free Software
|
|
22
|
-
# Foundation, Inc.,
|
|
23
|
-
#
|
|
22
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
24
23
|
# = SYNOPSIS
|
|
25
24
|
#
|
|
26
25
|
# require 'geoip'
|
|
@@ -59,7 +58,7 @@ require 'yaml'
|
|
|
59
58
|
class GeoIP
|
|
60
59
|
|
|
61
60
|
# The GeoIP GEM version number
|
|
62
|
-
VERSION = "1.
|
|
61
|
+
VERSION = "1.3.0"
|
|
63
62
|
|
|
64
63
|
# The +data/+ directory for geoip
|
|
65
64
|
DATA_DIR = File.expand_path(File.join(File.dirname(__FILE__),'..','data','geoip'))
|
|
@@ -79,6 +78,9 @@ class GeoIP
|
|
|
79
78
|
# ordered by GeoIP ID
|
|
80
79
|
CountryContinent = YAML.load_file(File.join(DATA_DIR,'country_continent.yml'))
|
|
81
80
|
|
|
81
|
+
# Load a hash of region names by region code
|
|
82
|
+
RegionName = YAML.load_file(File.join(DATA_DIR,'region.yml'))
|
|
83
|
+
|
|
82
84
|
# Hash of the timezone codes mapped to timezone name, per zoneinfo
|
|
83
85
|
TimeZone = YAML.load_file(File.join(DATA_DIR,'time_zone.yml'))
|
|
84
86
|
|
|
@@ -92,6 +94,7 @@ class GeoIP
|
|
|
92
94
|
GEOIP_PROXY_EDITION = 8
|
|
93
95
|
GEOIP_ASNUM_EDITION = 9
|
|
94
96
|
GEOIP_NETSPEED_EDITION = 10
|
|
97
|
+
GEOIP_COUNTRY_EDITION_V6 = 12
|
|
95
98
|
GEOIP_CITY_EDITION_REV1_V6 = 30
|
|
96
99
|
|
|
97
100
|
COUNTRY_BEGIN = 16776960 #:nodoc:
|
|
@@ -118,13 +121,27 @@ class GeoIP
|
|
|
118
121
|
|
|
119
122
|
end
|
|
120
123
|
|
|
124
|
+
class Region < Struct.new(:request, :ip, :country_code2, :country_code3, :country_name, :continent_code,
|
|
125
|
+
:region_code, :region_name, :timezone)
|
|
126
|
+
|
|
127
|
+
def to_hash
|
|
128
|
+
Hash[each_pair.to_a]
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Warning: for historical reasons the region code is mis-named region_name here
|
|
121
134
|
class City < Struct.new(:request, :ip, :country_code2, :country_code3, :country_name, :continent_code,
|
|
122
|
-
:region_name, :city_name, :postal_code, :latitude, :longitude, :dma_code, :area_code, :timezone)
|
|
135
|
+
:region_name, :city_name, :postal_code, :latitude, :longitude, :dma_code, :area_code, :timezone, :real_region_name)
|
|
123
136
|
|
|
124
137
|
def to_hash
|
|
125
138
|
Hash[each_pair.to_a]
|
|
126
139
|
end
|
|
127
140
|
|
|
141
|
+
def region_code
|
|
142
|
+
self.region_name
|
|
143
|
+
end
|
|
144
|
+
|
|
128
145
|
end
|
|
129
146
|
|
|
130
147
|
class ASN < Struct.new(:number, :asn)
|
|
@@ -136,6 +153,9 @@ class GeoIP
|
|
|
136
153
|
# The Edition number that identifies which kind of database you've opened
|
|
137
154
|
attr_reader :database_type
|
|
138
155
|
|
|
156
|
+
# An IP that is used instead of local IPs
|
|
157
|
+
attr_accessor :local_ip_alias
|
|
158
|
+
|
|
139
159
|
alias databaseType database_type
|
|
140
160
|
|
|
141
161
|
# Open the GeoIP database and determine the file format version.
|
|
@@ -182,17 +202,24 @@ class GeoIP
|
|
|
182
202
|
return city(hostname)
|
|
183
203
|
end
|
|
184
204
|
|
|
185
|
-
if (@database_type
|
|
186
|
-
@database_type
|
|
187
|
-
|
|
188
|
-
throw "Invalid GeoIP database type, can't look up Country by IP"
|
|
205
|
+
if (@database_type == GEOIP_REGION_EDITION_REV0 ||
|
|
206
|
+
@database_type == GEOIP_REGION_EDITION_REV1)
|
|
207
|
+
return region(hostname)
|
|
189
208
|
end
|
|
190
209
|
|
|
191
210
|
ip = lookup_ip(hostname)
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
211
|
+
if (@database_type == GEOIP_COUNTRY_EDITION ||
|
|
212
|
+
@database_type == GEOIP_PROXY_EDITION ||
|
|
213
|
+
@database_type == GEOIP_NETSPEED_EDITION)
|
|
214
|
+
# Convert numeric IP address to an integer
|
|
215
|
+
ipnum = iptonum(ip)
|
|
216
|
+
code = (seek_record(ipnum) - COUNTRY_BEGIN)
|
|
217
|
+
elsif @database_type == GEOIP_COUNTRY_EDITION_V6
|
|
218
|
+
ipaddr = IPAddr.new ip
|
|
219
|
+
code = (seek_record_v6(ipaddr.to_i) - COUNTRY_BEGIN)
|
|
220
|
+
else
|
|
221
|
+
throw "Invalid GeoIP database type, can't look up Country by IP"
|
|
222
|
+
end
|
|
196
223
|
|
|
197
224
|
Country.new(
|
|
198
225
|
hostname, # Requested hostname
|
|
@@ -205,6 +232,42 @@ class GeoIP
|
|
|
205
232
|
)
|
|
206
233
|
end
|
|
207
234
|
|
|
235
|
+
# Search the GeoIP database for the specified host, retuning region info.
|
|
236
|
+
#
|
|
237
|
+
# +hostname+ is a String holding the hosts's DNS name or numeric IP
|
|
238
|
+
# address.
|
|
239
|
+
#
|
|
240
|
+
# Returns a Region object with the nine elements:
|
|
241
|
+
# * The host or IP address string as requested
|
|
242
|
+
# * The IP address string after looking up the host
|
|
243
|
+
# * The two-character country code (ISO 3166-1 alpha-2)
|
|
244
|
+
# * The three-character country code (ISO 3166-2 alpha-3)
|
|
245
|
+
# * The ISO 3166 English-language name of the country
|
|
246
|
+
# * The two-character continent code
|
|
247
|
+
# * The region name (state or territory)
|
|
248
|
+
# * The timezone name, if known
|
|
249
|
+
#
|
|
250
|
+
def region(hostname)
|
|
251
|
+
if (@database_type == GEOIP_CITY_EDITION_REV0 ||
|
|
252
|
+
@database_type == GEOIP_CITY_EDITION_REV1 ||
|
|
253
|
+
@database_type == GEOIP_CITY_EDITION_REV1_V6)
|
|
254
|
+
return city(hostname)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
if (@database_type == GEOIP_REGION_EDITION_REV0 ||
|
|
258
|
+
@database_type == GEOIP_REGION_EDITION_REV1)
|
|
259
|
+
ip = lookup_ip(hostname)
|
|
260
|
+
ipnum = iptonum(ip)
|
|
261
|
+
pos = seek_record(ipnum)
|
|
262
|
+
else
|
|
263
|
+
throw "Invalid GeoIP database type, can't look up Region by IP"
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
unless pos == @database_segments[0]
|
|
267
|
+
read_region(pos, hostname, ip)
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
208
271
|
# Search the GeoIP database for the specified host, returning city info.
|
|
209
272
|
#
|
|
210
273
|
# +hostname+ is a String holding the host's DNS name or numeric IP
|
|
@@ -393,11 +456,57 @@ class GeoIP
|
|
|
393
456
|
|
|
394
457
|
if (@database_type == GEOIP_COUNTRY_EDITION ||
|
|
395
458
|
@database_type == GEOIP_PROXY_EDITION ||
|
|
459
|
+
@database_type == GEOIP_COUNTRY_EDITION_V6 ||
|
|
396
460
|
@database_type == GEOIP_NETSPEED_EDITION)
|
|
397
461
|
@database_segments = [COUNTRY_BEGIN]
|
|
398
462
|
end
|
|
399
463
|
end
|
|
400
464
|
|
|
465
|
+
def read_region(pos, hostname = '', ip = '') #:nodoc:
|
|
466
|
+
if (@database_type == GEOIP_REGION_EDITION_REV0)
|
|
467
|
+
pos -= STATE_BEGIN_REV0
|
|
468
|
+
if (pos >= 1000)
|
|
469
|
+
code = 225
|
|
470
|
+
region_code = ((pos - 1000) / 26 + 65).chr + ((pos - 1000) % 26 + 65).chr
|
|
471
|
+
else
|
|
472
|
+
code = pos
|
|
473
|
+
region_code = ''
|
|
474
|
+
end
|
|
475
|
+
elsif (@database_type == GEOIP_REGION_EDITION_REV1)
|
|
476
|
+
pos -= STATE_BEGIN_REV1
|
|
477
|
+
if (pos < US_OFFSET)
|
|
478
|
+
code = 0
|
|
479
|
+
region_code = ''
|
|
480
|
+
elsif (pos < CANADA_OFFSET)
|
|
481
|
+
code = 225
|
|
482
|
+
region_code = ((pos - US_OFFSET) / 26 + 65).chr + ((pos - US_OFFSET) % 26 + 65).chr
|
|
483
|
+
elsif (pos < WORLD_OFFSET)
|
|
484
|
+
code = 38
|
|
485
|
+
region_code = ((pos - CANADA_OFFSET) / 26 + 65).chr + ((pos - CANADA_OFFSET) % 26 + 65).chr
|
|
486
|
+
else
|
|
487
|
+
code = (pos - WORLD_OFFSET) / FIPS_RANGE
|
|
488
|
+
region_code = ''
|
|
489
|
+
end
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
Region.new(
|
|
493
|
+
hostname,
|
|
494
|
+
ip,
|
|
495
|
+
CountryCode[code], # ISO3166-1 alpha-2 code
|
|
496
|
+
CountryCode3[code], # ISO3166-2 alpha-3 code
|
|
497
|
+
CountryName[code], # Country name, per ISO 3166
|
|
498
|
+
CountryContinent[code], # Continent code.
|
|
499
|
+
region_code, # Unfortunately this is called region_name in the City structure
|
|
500
|
+
lookup_region_name(CountryCode[code], region_code),
|
|
501
|
+
(TimeZone["#{CountryCode[code]}#{region_code}"] || TimeZone["#{CountryCode[code]}"])
|
|
502
|
+
)
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
def lookup_region_name(country_iso2, region_code)
|
|
506
|
+
country_regions = RegionName[country_iso2]
|
|
507
|
+
country_regions && country_regions[region_code]
|
|
508
|
+
end
|
|
509
|
+
|
|
401
510
|
# Search the GeoIP database for the specified host, returning city info.
|
|
402
511
|
#
|
|
403
512
|
# +hostname+ is a String holding the host's DNS name or numeric
|
|
@@ -427,9 +536,9 @@ class GeoIP
|
|
|
427
536
|
@iter_pos += 1 unless @iter_pos.nil?
|
|
428
537
|
|
|
429
538
|
spl = record.split("\x00", 4)
|
|
430
|
-
# Get the region:
|
|
431
|
-
|
|
432
|
-
@iter_pos += (
|
|
539
|
+
# Get the region code:
|
|
540
|
+
region_code = spl[0]
|
|
541
|
+
@iter_pos += (region_code.size + 1) unless @iter_pos.nil?
|
|
433
542
|
|
|
434
543
|
# Get the city:
|
|
435
544
|
city = spl[1]
|
|
@@ -439,7 +548,7 @@ class GeoIP
|
|
|
439
548
|
|
|
440
549
|
# Get the postal code:
|
|
441
550
|
postal_code = spl[2]
|
|
442
|
-
@iter_pos += (postal_code.size + 1) unless @iter_pos.nil?
|
|
551
|
+
@iter_pos += (postal_code.size + 1) unless @iter_pos.nil? || postal_code.nil?
|
|
443
552
|
|
|
444
553
|
record = spl[3]
|
|
445
554
|
|
|
@@ -484,18 +593,23 @@ class GeoIP
|
|
|
484
593
|
CountryCode3[code], # ISO3166-2 code
|
|
485
594
|
CountryName[code], # Country name, per IS03166
|
|
486
595
|
CountryContinent[code], # Continent code.
|
|
487
|
-
|
|
596
|
+
region_code, # Region code (called region_name, unfortunately)
|
|
488
597
|
city, # City name
|
|
489
598
|
postal_code, # Postal code
|
|
490
599
|
latitude,
|
|
491
600
|
longitude,
|
|
492
601
|
dma_code,
|
|
493
602
|
area_code,
|
|
494
|
-
(TimeZone["#{CountryCode[code]}#{
|
|
603
|
+
(TimeZone["#{CountryCode[code]}#{region_code}"] || TimeZone["#{CountryCode[code]}"]),
|
|
604
|
+
lookup_region_name(CountryCode[code], region_code) # Real region name
|
|
495
605
|
)
|
|
496
606
|
end
|
|
497
607
|
|
|
498
608
|
def lookup_ip(ip_or_hostname) # :nodoc:
|
|
609
|
+
if is_local?(ip_or_hostname) && @local_ip_alias
|
|
610
|
+
ip_or_hostname = @local_ip_alias
|
|
611
|
+
end
|
|
612
|
+
|
|
499
613
|
if !ip_or_hostname.kind_of?(String) or ip_or_hostname =~ /^[0-9.]+$/
|
|
500
614
|
return ip_or_hostname
|
|
501
615
|
end
|
|
@@ -506,6 +620,10 @@ class GeoIP
|
|
|
506
620
|
ip
|
|
507
621
|
end
|
|
508
622
|
|
|
623
|
+
def is_local?(ip_or_hostname) #:nodoc:
|
|
624
|
+
["127.0.0.1", "localhost", "::1", "0000::1", "0:0:0:0:0:0:0:1"].include? ip_or_hostname
|
|
625
|
+
end
|
|
626
|
+
|
|
509
627
|
# Convert numeric IP address to Integer.
|
|
510
628
|
def iptonum(ip) #:nodoc:
|
|
511
629
|
if (ip.kind_of?(String) &&
|
data/script/txt2html
CHANGED
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require 'rubygems'
|
|
4
4
|
require 'redcloth'
|
|
5
|
-
require 'syntax/convertors/html'
|
|
6
5
|
require 'erb'
|
|
7
|
-
require File.dirname(__FILE__) + '/../lib/geoip.rb'
|
|
6
|
+
require './' + File.dirname(__FILE__) + '/../lib/geoip.rb'
|
|
8
7
|
|
|
9
8
|
version = GeoIP::VERSION
|
|
10
9
|
download = 'http://rubyforge.org/projects/geoip'
|
|
@@ -15,9 +14,9 @@ class Fixnum
|
|
|
15
14
|
return 'th' if (10..19).include?(self % 100)
|
|
16
15
|
# others
|
|
17
16
|
case self % 10
|
|
18
|
-
when 1
|
|
19
|
-
when 2
|
|
20
|
-
when 3
|
|
17
|
+
when 1; return 'st'
|
|
18
|
+
when 2; return 'nd'
|
|
19
|
+
when 3; return 'rd'
|
|
21
20
|
else return 'th'
|
|
22
21
|
end
|
|
23
22
|
end
|
data/website/index.txt
CHANGED
|
@@ -65,15 +65,15 @@ This version Copyright (C) 2005 Clifford Heath
|
|
|
65
65
|
Derived from the C version, Copyright (C) 2003 MaxMind LLC
|
|
66
66
|
|
|
67
67
|
This library is free software; you can redistribute it and/or
|
|
68
|
-
modify it under the terms of the GNU General Public
|
|
68
|
+
modify it under the terms of the GNU Lesser General Public
|
|
69
69
|
License as published by the Free Software Foundation; either
|
|
70
70
|
version 2.1 of the License, or (at your option) any later version.
|
|
71
71
|
|
|
72
72
|
This library is distributed in the hope that it will be useful,
|
|
73
73
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
74
74
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
75
|
-
General Public License for more details.
|
|
75
|
+
Lesser General Public License for more details.
|
|
76
76
|
|
|
77
|
-
You should have received a copy of the GNU General Public
|
|
77
|
+
You should have received a copy of the GNU Lesser General Public
|
|
78
78
|
License along with this library; if not, write to the Free Software
|
|
79
|
-
Foundation, Inc.,
|
|
79
|
+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
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.3.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:
|
|
13
|
+
date: 2013-08-13 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
|
|
|
@@ -35,6 +35,7 @@ files:
|
|
|
35
35
|
- data/geoip/country_code3.yml
|
|
36
36
|
- data/geoip/country_continent.yml
|
|
37
37
|
- data/geoip/country_name.yml
|
|
38
|
+
- data/geoip/region.yml
|
|
38
39
|
- data/geoip/time_zone.yml
|
|
39
40
|
- geoip.gemspec
|
|
40
41
|
- lib/geoip.rb
|
|
@@ -49,7 +50,7 @@ files:
|
|
|
49
50
|
- website/template.rhtml
|
|
50
51
|
homepage: http://github.com/cjheath/geoip
|
|
51
52
|
licenses:
|
|
52
|
-
-
|
|
53
|
+
- LGPL
|
|
53
54
|
post_install_message:
|
|
54
55
|
rdoc_options: []
|
|
55
56
|
require_paths:
|