geoip 1.2.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/data/geoip/region.yml +4249 -0
  2. data/geoip.gemspec +3 -2
  3. data/lib/geoip.rb +111 -7
  4. metadata +3 -2
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.2.2"
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 = "2013-08-05"
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",
data/lib/geoip.rb CHANGED
@@ -58,7 +58,7 @@ require 'yaml'
58
58
  class GeoIP
59
59
 
60
60
  # The GeoIP GEM version number
61
- VERSION = "1.2.2"
61
+ VERSION = "1.3.0"
62
62
 
63
63
  # The +data/+ directory for geoip
64
64
  DATA_DIR = File.expand_path(File.join(File.dirname(__FILE__),'..','data','geoip'))
@@ -78,6 +78,9 @@ class GeoIP
78
78
  # ordered by GeoIP ID
79
79
  CountryContinent = YAML.load_file(File.join(DATA_DIR,'country_continent.yml'))
80
80
 
81
+ # Load a hash of region names by region code
82
+ RegionName = YAML.load_file(File.join(DATA_DIR,'region.yml'))
83
+
81
84
  # Hash of the timezone codes mapped to timezone name, per zoneinfo
82
85
  TimeZone = YAML.load_file(File.join(DATA_DIR,'time_zone.yml'))
83
86
 
@@ -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)
@@ -185,6 +202,11 @@ class GeoIP
185
202
  return city(hostname)
186
203
  end
187
204
 
205
+ if (@database_type == GEOIP_REGION_EDITION_REV0 ||
206
+ @database_type == GEOIP_REGION_EDITION_REV1)
207
+ return region(hostname)
208
+ end
209
+
188
210
  ip = lookup_ip(hostname)
189
211
  if (@database_type == GEOIP_COUNTRY_EDITION ||
190
212
  @database_type == GEOIP_PROXY_EDITION ||
@@ -210,6 +232,42 @@ class GeoIP
210
232
  )
211
233
  end
212
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
+
213
271
  # Search the GeoIP database for the specified host, returning city info.
214
272
  #
215
273
  # +hostname+ is a String holding the host's DNS name or numeric IP
@@ -404,6 +462,51 @@ class GeoIP
404
462
  end
405
463
  end
406
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
+
407
510
  # Search the GeoIP database for the specified host, returning city info.
408
511
  #
409
512
  # +hostname+ is a String holding the host's DNS name or numeric
@@ -433,9 +536,9 @@ class GeoIP
433
536
  @iter_pos += 1 unless @iter_pos.nil?
434
537
 
435
538
  spl = record.split("\x00", 4)
436
- # Get the region:
437
- region = spl[0]
438
- @iter_pos += (region.size + 1) unless @iter_pos.nil?
539
+ # Get the region code:
540
+ region_code = spl[0]
541
+ @iter_pos += (region_code.size + 1) unless @iter_pos.nil?
439
542
 
440
543
  # Get the city:
441
544
  city = spl[1]
@@ -490,14 +593,15 @@ class GeoIP
490
593
  CountryCode3[code], # ISO3166-2 code
491
594
  CountryName[code], # Country name, per IS03166
492
595
  CountryContinent[code], # Continent code.
493
- region, # Region name
596
+ region_code, # Region code (called region_name, unfortunately)
494
597
  city, # City name
495
598
  postal_code, # Postal code
496
599
  latitude,
497
600
  longitude,
498
601
  dma_code,
499
602
  area_code,
500
- (TimeZone["#{CountryCode[code]}#{region}"] || TimeZone["#{CountryCode[code]}"])
603
+ (TimeZone["#{CountryCode[code]}#{region_code}"] || TimeZone["#{CountryCode[code]}"]),
604
+ lookup_region_name(CountryCode[code], region_code) # Real region name
501
605
  )
502
606
  end
503
607
 
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.2.2
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: 2013-08-05 00:00:00.000000000 Z
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