maxmind-geoip2 0.2.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +33 -0
  3. data/Gemfile +1 -7
  4. data/README.dev.md +1 -1
  5. data/README.md +36 -14
  6. data/lib/maxmind/geoip2/client.rb +289 -265
  7. data/lib/maxmind/geoip2/errors.rb +0 -7
  8. data/lib/maxmind/geoip2/model/abstract.rb +19 -15
  9. data/lib/maxmind/geoip2/model/anonymous_ip.rb +62 -50
  10. data/lib/maxmind/geoip2/model/asn.rb +33 -29
  11. data/lib/maxmind/geoip2/model/city.rb +59 -55
  12. data/lib/maxmind/geoip2/model/connection_type.rb +27 -23
  13. data/lib/maxmind/geoip2/model/country.rb +57 -53
  14. data/lib/maxmind/geoip2/model/domain.rb +27 -23
  15. data/lib/maxmind/geoip2/model/enterprise.rb +13 -9
  16. data/lib/maxmind/geoip2/model/insights.rb +12 -8
  17. data/lib/maxmind/geoip2/model/isp.rb +45 -41
  18. data/lib/maxmind/geoip2/reader.rb +260 -233
  19. data/lib/maxmind/geoip2/record/abstract.rb +17 -13
  20. data/lib/maxmind/geoip2/record/city.rb +33 -29
  21. data/lib/maxmind/geoip2/record/continent.rb +32 -28
  22. data/lib/maxmind/geoip2/record/country.rb +47 -43
  23. data/lib/maxmind/geoip2/record/location.rb +64 -60
  24. data/lib/maxmind/geoip2/record/maxmind.rb +14 -10
  25. data/lib/maxmind/geoip2/record/place.rb +22 -18
  26. data/lib/maxmind/geoip2/record/postal.rb +26 -22
  27. data/lib/maxmind/geoip2/record/represented_country.rb +20 -16
  28. data/lib/maxmind/geoip2/record/subdivision.rb +42 -38
  29. data/lib/maxmind/geoip2/record/traits.rb +204 -191
  30. data/maxmind-geoip2.gemspec +10 -3
  31. data/test/data/LICENSE +4 -0
  32. data/test/data/MaxMind-DB-spec.md +570 -0
  33. data/test/data/MaxMind-DB-test-metadata-pointers.mmdb +0 -0
  34. data/test/data/README.md +4 -0
  35. data/test/data/bad-data/README.md +7 -0
  36. data/test/data/bad-data/libmaxminddb/libmaxminddb-offset-integer-overflow.mmdb +0 -0
  37. data/test/data/bad-data/maxminddb-golang/cyclic-data-structure.mmdb +0 -0
  38. data/test/data/bad-data/maxminddb-golang/invalid-bytes-length.mmdb +1 -0
  39. data/test/data/bad-data/maxminddb-golang/invalid-data-record-offset.mmdb +0 -0
  40. data/test/data/bad-data/maxminddb-golang/invalid-map-key-length.mmdb +0 -0
  41. data/test/data/bad-data/maxminddb-golang/invalid-string-length.mmdb +1 -0
  42. data/test/data/bad-data/maxminddb-golang/metadata-is-an-uint128.mmdb +1 -0
  43. data/test/data/bad-data/maxminddb-golang/unexpected-bytes.mmdb +0 -0
  44. data/test/data/bad-data/maxminddb-python/bad-unicode-in-map-key.mmdb +0 -0
  45. data/test/data/perltidyrc +12 -0
  46. data/test/data/source-data/GeoIP2-Anonymous-IP-Test.json +49 -0
  47. data/test/data/source-data/GeoIP2-City-Test.json +12852 -0
  48. data/test/data/source-data/GeoIP2-Connection-Type-Test.json +102 -0
  49. data/test/data/source-data/GeoIP2-Country-Test.json +15916 -0
  50. data/test/data/source-data/GeoIP2-DensityIncome-Test.json +14 -0
  51. data/test/data/source-data/GeoIP2-Domain-Test.json +452 -0
  52. data/test/data/source-data/GeoIP2-Enterprise-Test.json +687 -0
  53. data/test/data/source-data/GeoIP2-ISP-Test.json +12595 -0
  54. data/test/data/source-data/GeoIP2-Precision-Enterprise-Test.json +2148 -0
  55. data/test/data/source-data/GeoIP2-Static-IP-Score-Test.json +2132 -0
  56. data/test/data/source-data/GeoIP2-User-Count-Test.json +2837 -0
  57. data/test/data/source-data/GeoLite2-ASN-Test.json +37 -0
  58. data/test/data/source-data/README +15 -0
  59. data/test/data/test-data/GeoIP2-Anonymous-IP-Test.mmdb +0 -0
  60. data/test/data/test-data/GeoIP2-City-Test-Broken-Double-Format.mmdb +0 -0
  61. data/test/data/test-data/GeoIP2-City-Test-Invalid-Node-Count.mmdb +0 -0
  62. data/test/data/test-data/GeoIP2-City-Test.mmdb +0 -0
  63. data/test/data/test-data/GeoIP2-Connection-Type-Test.mmdb +0 -0
  64. data/test/data/test-data/GeoIP2-Country-Test.mmdb +0 -0
  65. data/test/data/test-data/GeoIP2-DensityIncome-Test.mmdb +0 -0
  66. data/test/data/test-data/GeoIP2-Domain-Test.mmdb +0 -0
  67. data/test/data/test-data/GeoIP2-Enterprise-Test.mmdb +0 -0
  68. data/test/data/test-data/GeoIP2-ISP-Test.mmdb +0 -0
  69. data/test/data/test-data/GeoIP2-Precision-Enterprise-Test.mmdb +0 -0
  70. data/test/data/test-data/GeoIP2-Static-IP-Score-Test.mmdb +0 -0
  71. data/test/data/test-data/GeoIP2-User-Count-Test.mmdb +0 -0
  72. data/test/data/test-data/GeoLite2-ASN-Test.mmdb +0 -0
  73. data/test/data/test-data/MaxMind-DB-no-ipv4-search-tree.mmdb +0 -0
  74. data/test/data/test-data/MaxMind-DB-string-value-entries.mmdb +0 -0
  75. data/test/data/test-data/MaxMind-DB-test-broken-pointers-24.mmdb +0 -0
  76. data/test/data/test-data/MaxMind-DB-test-broken-search-tree-24.mmdb +0 -0
  77. data/test/data/test-data/MaxMind-DB-test-decoder.mmdb +0 -0
  78. data/test/data/test-data/MaxMind-DB-test-ipv4-24.mmdb +0 -0
  79. data/test/data/test-data/MaxMind-DB-test-ipv4-28.mmdb +0 -0
  80. data/test/data/test-data/MaxMind-DB-test-ipv4-32.mmdb +0 -0
  81. data/test/data/test-data/MaxMind-DB-test-ipv6-24.mmdb +0 -0
  82. data/test/data/test-data/MaxMind-DB-test-ipv6-28.mmdb +0 -0
  83. data/test/data/test-data/MaxMind-DB-test-ipv6-32.mmdb +0 -0
  84. data/test/data/test-data/MaxMind-DB-test-metadata-pointers.mmdb +0 -0
  85. data/test/data/test-data/MaxMind-DB-test-mixed-24.mmdb +0 -0
  86. data/test/data/test-data/MaxMind-DB-test-mixed-28.mmdb +0 -0
  87. data/test/data/test-data/MaxMind-DB-test-mixed-32.mmdb +0 -0
  88. data/test/data/test-data/MaxMind-DB-test-nested.mmdb +0 -0
  89. data/test/data/test-data/MaxMind-DB-test-pointer-decoder.mmdb +0 -0
  90. data/test/data/test-data/README.md +26 -0
  91. data/test/data/test-data/maps-with-pointers.raw +0 -0
  92. data/test/data/test-data/write-test-data.pl +691 -0
  93. data/test/data/tidyall.ini +5 -0
  94. data/test/test_client.rb +4 -2
  95. data/test/test_model_country.rb +16 -0
  96. data/test/test_reader.rb +59 -0
  97. metadata +156 -10
  98. data/Gemfile.lock +0 -70
@@ -6,65 +6,69 @@ require 'maxmind/geoip2/record/maxmind'
6
6
  require 'maxmind/geoip2/record/represented_country'
7
7
  require 'maxmind/geoip2/record/traits'
8
8
 
9
- module MaxMind::GeoIP2::Model
10
- # Model class for the data returned by the GeoIP2 Country web service and
11
- # database. It is also used for GeoLite2 Country lookups.
12
- class Country
13
- # Continent data for the IP address.
14
- #
15
- # @return [MaxMind::GeoIP2::Record::Continent]
16
- attr_reader :continent
9
+ module MaxMind
10
+ module GeoIP2
11
+ module Model
12
+ # Model class for the data returned by the GeoIP2 Country web service and
13
+ # database. It is also used for GeoLite2 Country lookups.
14
+ class Country
15
+ # Continent data for the IP address.
16
+ #
17
+ # @return [MaxMind::GeoIP2::Record::Continent]
18
+ attr_reader :continent
17
19
 
18
- # Country data for the IP address. This object represents the country where
19
- # MaxMind believes the end user is located.
20
- #
21
- # @return [MaxMind::GeoIP2::Record::Country]
22
- attr_reader :country
20
+ # Country data for the IP address. This object represents the country where
21
+ # MaxMind believes the end user is located.
22
+ #
23
+ # @return [MaxMind::GeoIP2::Record::Country]
24
+ attr_reader :country
23
25
 
24
- # Data related to your MaxMind account.
25
- #
26
- # @return [MaxMind::GeoIP2::Record::MaxMind]
27
- attr_reader :maxmind
26
+ # Data related to your MaxMind account.
27
+ #
28
+ # @return [MaxMind::GeoIP2::Record::MaxMind]
29
+ attr_reader :maxmind
28
30
 
29
- # Registered country data for the IP address. This record represents the
30
- # country where the ISP has registered a given IP block and may differ from
31
- # the user's country.
32
- #
33
- # @return [MaxMind::GeoIP2::Record::Country]
34
- attr_reader :registered_country
31
+ # Registered country data for the IP address. This record represents the
32
+ # country where the ISP has registered a given IP block and may differ from
33
+ # the user's country.
34
+ #
35
+ # @return [MaxMind::GeoIP2::Record::Country]
36
+ attr_reader :registered_country
35
37
 
36
- # Represented country data for the IP address. The represented country is
37
- # used for things like military bases. It is only present when the
38
- # represented country differs from the country.
39
- #
40
- # @return [MaxMind::GeoIP2::Record::RepresentedCountry]
41
- attr_reader :represented_country
38
+ # Represented country data for the IP address. The represented country is
39
+ # used for things like military bases. It is only present when the
40
+ # represented country differs from the country.
41
+ #
42
+ # @return [MaxMind::GeoIP2::Record::RepresentedCountry]
43
+ attr_reader :represented_country
42
44
 
43
- # Data for the traits of the IP address.
44
- #
45
- # @return [MaxMind::GeoIP2::Record::Traits]
46
- attr_reader :traits
45
+ # Data for the traits of the IP address.
46
+ #
47
+ # @return [MaxMind::GeoIP2::Record::Traits]
48
+ attr_reader :traits
47
49
 
48
- # @!visibility private
49
- def initialize(record, locales)
50
- @continent = MaxMind::GeoIP2::Record::Continent.new(
51
- record['continent'],
52
- locales,
53
- )
54
- @country = MaxMind::GeoIP2::Record::Country.new(
55
- record['country'],
56
- locales,
57
- )
58
- @maxmind = MaxMind::GeoIP2::Record::MaxMind.new(record['maxmind'])
59
- @registered_country = MaxMind::GeoIP2::Record::Country.new(
60
- record['registered_country'],
61
- locales,
62
- )
63
- @represented_country = MaxMind::GeoIP2::Record::RepresentedCountry.new(
64
- record['represented_country'],
65
- locales,
66
- )
67
- @traits = MaxMind::GeoIP2::Record::Traits.new(record['traits'])
50
+ # @!visibility private
51
+ def initialize(record, locales)
52
+ @continent = MaxMind::GeoIP2::Record::Continent.new(
53
+ record['continent'],
54
+ locales,
55
+ )
56
+ @country = MaxMind::GeoIP2::Record::Country.new(
57
+ record['country'],
58
+ locales,
59
+ )
60
+ @maxmind = MaxMind::GeoIP2::Record::MaxMind.new(record['maxmind'])
61
+ @registered_country = MaxMind::GeoIP2::Record::Country.new(
62
+ record['registered_country'],
63
+ locales,
64
+ )
65
+ @represented_country = MaxMind::GeoIP2::Record::RepresentedCountry.new(
66
+ record['represented_country'],
67
+ locales,
68
+ )
69
+ @traits = MaxMind::GeoIP2::Record::Traits.new(record['traits'])
70
+ end
71
+ end
68
72
  end
69
73
  end
70
74
  end
@@ -2,31 +2,35 @@
2
2
 
3
3
  require 'maxmind/geoip2/model/abstract'
4
4
 
5
- module MaxMind::GeoIP2::Model
6
- # Model class for the GeoIP2 Domain database.
7
- class Domain < Abstract
8
- # The second level domain associated with the IP address. This will be
9
- # something like "example.com" or "example.co.uk", not "foo.example.com".
10
- #
11
- # @return [String, nil]
12
- def domain
13
- get('domain')
14
- end
5
+ module MaxMind
6
+ module GeoIP2
7
+ module Model
8
+ # Model class for the GeoIP2 Domain database.
9
+ class Domain < Abstract
10
+ # The second level domain associated with the IP address. This will be
11
+ # something like "example.com" or "example.co.uk", not "foo.example.com".
12
+ #
13
+ # @return [String, nil]
14
+ def domain
15
+ get('domain')
16
+ end
15
17
 
16
- # The IP address that the data in the model is for.
17
- #
18
- # @return [String]
19
- def ip_address
20
- get('ip_address')
21
- end
18
+ # The IP address that the data in the model is for.
19
+ #
20
+ # @return [String]
21
+ def ip_address
22
+ get('ip_address')
23
+ end
22
24
 
23
- # The network in CIDR notation associated with the record. In particular,
24
- # this is the largest network where all of the fields besides ip_address
25
- # have the same value.
26
- #
27
- # @return [String]
28
- def network
29
- get('network')
25
+ # The network in CIDR notation associated with the record. In particular,
26
+ # this is the largest network where all of the fields besides ip_address
27
+ # have the same value.
28
+ #
29
+ # @return [String]
30
+ def network
31
+ get('network')
32
+ end
33
+ end
30
34
  end
31
35
  end
32
36
  end
@@ -2,14 +2,18 @@
2
2
 
3
3
  require 'maxmind/geoip2/model/city'
4
4
 
5
- module MaxMind::GeoIP2::Model
6
- # Model class for the data returned by GeoIP2 Enterprise database lookups.
7
- #
8
- # The only difference between the City and Insights model classes is which
9
- # fields in each record may be populated. See
10
- # https://dev.maxmind.com/geoip/geoip2/web-services for more details.
11
- #
12
- # See {MaxMind::GeoIP2::Model::City} for inherited methods.
13
- class Enterprise < City
5
+ module MaxMind
6
+ module GeoIP2
7
+ module Model
8
+ # Model class for the data returned by GeoIP2 Enterprise database lookups.
9
+ #
10
+ # The only difference between the City and Insights model classes is which
11
+ # fields in each record may be populated. See
12
+ # https://dev.maxmind.com/geoip/geoip2/web-services for more details.
13
+ #
14
+ # See {MaxMind::GeoIP2::Model::City} for inherited methods.
15
+ class Enterprise < City
16
+ end
17
+ end
14
18
  end
15
19
  end
@@ -2,13 +2,17 @@
2
2
 
3
3
  require 'maxmind/geoip2/model/city'
4
4
 
5
- module MaxMind::GeoIP2::Model
6
- # Model class for the data returned by the GeoIP2 Precision Insights web
7
- # service.
8
- #
9
- # The only difference between the City and Insights model classes is which
10
- # fields in each record may be populated. See
11
- # https://dev.maxmind.com/geoip/geoip2/web-services for more details.
12
- class Insights < City
5
+ module MaxMind
6
+ module GeoIP2
7
+ module Model
8
+ # Model class for the data returned by the GeoIP2 Precision Insights web
9
+ # service.
10
+ #
11
+ # The only difference between the City and Insights model classes is which
12
+ # fields in each record may be populated. See
13
+ # https://dev.maxmind.com/geoip/geoip2/web-services for more details.
14
+ class Insights < City
15
+ end
16
+ end
13
17
  end
14
18
  end
@@ -2,52 +2,56 @@
2
2
 
3
3
  require 'maxmind/geoip2/model/abstract'
4
4
 
5
- module MaxMind::GeoIP2::Model
6
- # Model class for the GeoIP2 ISP database.
7
- class ISP < Abstract
8
- # The autonomous system number associated with the IP address.
9
- #
10
- # @return [Integer, nil]
11
- def autonomous_system_number
12
- get('autonomous_system_number')
13
- end
5
+ module MaxMind
6
+ module GeoIP2
7
+ module Model
8
+ # Model class for the GeoIP2 ISP database.
9
+ class ISP < Abstract
10
+ # The autonomous system number associated with the IP address.
11
+ #
12
+ # @return [Integer, nil]
13
+ def autonomous_system_number
14
+ get('autonomous_system_number')
15
+ end
14
16
 
15
- # The organization associated with the registered autonomous system number
16
- # for the IP address.
17
- #
18
- # @return [String, nil]
19
- def autonomous_system_organization
20
- get('autonomous_system_organization')
21
- end
17
+ # The organization associated with the registered autonomous system number
18
+ # for the IP address.
19
+ #
20
+ # @return [String, nil]
21
+ def autonomous_system_organization
22
+ get('autonomous_system_organization')
23
+ end
22
24
 
23
- # The IP address that the data in the model is for.
24
- #
25
- # @return [String]
26
- def ip_address
27
- get('ip_address')
28
- end
25
+ # The IP address that the data in the model is for.
26
+ #
27
+ # @return [String]
28
+ def ip_address
29
+ get('ip_address')
30
+ end
29
31
 
30
- # The name of the ISP associated with the IP address.
31
- #
32
- # @return [String, nil]
33
- def isp
34
- get('isp')
35
- end
32
+ # The name of the ISP associated with the IP address.
33
+ #
34
+ # @return [String, nil]
35
+ def isp
36
+ get('isp')
37
+ end
36
38
 
37
- # The network in CIDR notation associated with the record. In particular,
38
- # this is the largest network where all of the fields besides ip_address
39
- # have the same value.
40
- #
41
- # @return [String]
42
- def network
43
- get('network')
44
- end
39
+ # The network in CIDR notation associated with the record. In particular,
40
+ # this is the largest network where all of the fields besides ip_address
41
+ # have the same value.
42
+ #
43
+ # @return [String]
44
+ def network
45
+ get('network')
46
+ end
45
47
 
46
- # The name of the organization associated with the IP address.
47
- #
48
- # @return [String, nil]
49
- def organization
50
- get('organization')
48
+ # The name of the organization associated with the IP address.
49
+ #
50
+ # @return [String, nil]
51
+ def organization
52
+ get('organization')
53
+ end
54
+ end
51
55
  end
52
56
  end
53
57
  end
@@ -11,267 +11,294 @@ require 'maxmind/geoip2/model/domain'
11
11
  require 'maxmind/geoip2/model/enterprise'
12
12
  require 'maxmind/geoip2/model/isp'
13
13
 
14
- module MaxMind::GeoIP2
15
- # Reader is a reader for the GeoIP2/GeoLite2 database format. IP addresses
16
- # can be looked up using the database specific methods.
17
- #
18
- # == Example
19
- #
20
- # require 'maxmind/geoip2'
21
- #
22
- # reader = MaxMind::GeoIP2::Reader.new('GeoIP2-Country.mmdb')
23
- #
24
- # record = reader.country('1.2.3.4')
25
- # puts record.country.iso_code
26
- #
27
- # reader.close
28
- class Reader
29
- # Create a Reader for looking up IP addresses in a GeoIP2/GeoLite2 database
30
- # file.
14
+ module MaxMind
15
+ module GeoIP2
16
+ # Reader is a reader for the GeoIP2/GeoLite2 database format. IP addresses
17
+ # can be looked up using the database specific methods.
31
18
  #
32
- # If you're performing multiple lookups, it's most efficient to create one
33
- # Reader and reuse it.
19
+ # == Example
34
20
  #
35
- # Once created, the Reader is safe to use for lookups from multiple
36
- # threads. It is safe to use after forking only if you use
37
- # MaxMind::DB::MODE_MEMORY or if your version of Ruby supports IO#pread.
21
+ # require 'maxmind/geoip2'
38
22
  #
39
- # @param database [String] a path to a GeoIP2/GeoLite2 database file.
23
+ # reader = MaxMind::GeoIP2::Reader.new(database: 'GeoIP2-Country.mmdb')
40
24
  #
41
- # @param locales [Array<String>] a list of locale codes to use in the name
42
- # property from most preferred to least preferred.
25
+ # record = reader.country('1.2.3.4')
26
+ # puts record.country.iso_code
43
27
  #
44
- # @param options [Hash<Symbol, Symbol>] options controlling the behavior of
45
- # the Reader.
46
- #
47
- # @option options [Symbol] :mode Defines how to open the database. It may
48
- # be one of MaxMind::DB::MODE_AUTO, MaxMind::DB::MODE_FILE, or
49
- # MaxMind::DB::MODE_MEMORY. If you don't provide one, the Reader uses
50
- # MaxMind::DB::MODE_AUTO. Refer to the definition of those constants in
51
- # MaxMind::DB for an explanation of their meaning.
52
- #
53
- # @raise [MaxMind::DB::InvalidDatabaseError] if the database is corrupt or
54
- # invalid.
55
- #
56
- # @raise [ArgumentError] if the mode is invalid.
57
- def initialize(database, locales = ['en'], options = {})
58
- @reader = MaxMind::DB.new(database, options)
59
- @type = @reader.metadata.database_type
60
- locales = ['en'] if locales.empty?
61
- @locales = locales
62
- end
28
+ # reader.close
29
+ class Reader
30
+ # rubocop:disable Metrics/CyclomaticComplexity
31
+ # rubocop:disable Metrics/PerceivedComplexity
63
32
 
64
- # Look up the IP address in the database.
65
- #
66
- # @param ip_address [String] a string in the standard notation. It may be
67
- # IPv4 or IPv6.
68
- #
69
- # @return [MaxMind::GeoIP2::Model::AnonymousIP]
70
- #
71
- # @raise [ArgumentError] if used against a non-Anonymous IP database or if
72
- # you attempt to look up an IPv6 address in an IPv4 only database.
73
- #
74
- # @raise [AddressNotFoundError] if the IP address is not found in the
75
- # database.
76
- #
77
- # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
78
- # corrupt.
79
- def anonymous_ip(ip_address)
80
- flat_model_for(
81
- Model::AnonymousIP,
82
- 'anonymous_ip',
83
- 'GeoIP2-Anonymous-IP',
84
- ip_address,
85
- )
86
- end
33
+ # Create a Reader for looking up IP addresses in a GeoIP2/GeoLite2 database
34
+ # file.
35
+ #
36
+ # If you're performing multiple lookups, it's most efficient to create one
37
+ # Reader and reuse it.
38
+ #
39
+ # Once created, the Reader is safe to use for lookups from multiple
40
+ # threads. It is safe to use after forking only if you use
41
+ # MaxMind::DB::MODE_MEMORY or if your version of Ruby supports IO#pread.
42
+ #
43
+ # @overload initialize(database:, locales: ['en'], mode: MaxMind::DB::MODE_AUTO)
44
+ # @param database [String] a path to a GeoIP2/GeoLite2 database file.
45
+ # @param locales [Array<String>] a list of locale codes to use in the name
46
+ # property from most preferred to least preferred.
47
+ # @param mode [Symbol] Defines how to open the database. It may be one of
48
+ # MaxMind::DB::MODE_AUTO, MaxMind::DB::MODE_FILE, or
49
+ # MaxMind::DB::MODE_MEMORY. If you don't provide one, the Reader uses
50
+ # MaxMind::DB::MODE_AUTO. Refer to the definition of those constants in
51
+ # MaxMind::DB for an explanation of their meaning.
52
+ #
53
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database is corrupt
54
+ # or invalid.
55
+ #
56
+ # @raise [ArgumentError] if the mode is invalid.
57
+ def initialize(*args)
58
+ # This if statement is to let us support calling as though we are using
59
+ # Ruby 2.0 keyword arguments. We can't use keyword argument syntax as
60
+ # we want to be backwards compatible with the old way we accepted
61
+ # parameters, which looked like:
62
+ # def initialize(database, locales = ['en'], options = {})
63
+ if args.length == 1 && args[0].instance_of?(Hash)
64
+ database = args[0][:database]
65
+ locales = args[0][:locales]
66
+ mode = args[0][:mode]
67
+ else
68
+ database = args[0]
69
+ locales = args[1]
70
+ mode = args[2].instance_of?(Hash) ? args[2][:mode] : nil
71
+ end
87
72
 
88
- # Look up the IP address in an ASN database.
89
- #
90
- # @param ip_address [String] a string in the standard notation. It may be
91
- # IPv4 or IPv6.
92
- #
93
- # @return [MaxMind::GeoIP2::Model::ASN]
94
- #
95
- # @raise [ArgumentError] if used against a non-ASN database or if you
96
- # attempt to look up an IPv6 address in an IPv4 only database.
97
- #
98
- # @raise [AddressNotFoundError] if the IP address is not found in the
99
- # database.
100
- #
101
- # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
102
- # corrupt.
103
- def asn(ip_address)
104
- flat_model_for(Model::ASN, 'asn', 'GeoLite2-ASN', ip_address)
105
- end
73
+ if !database.instance_of?(String)
74
+ raise ArgumentError, 'Invalid database parameter'
75
+ end
106
76
 
107
- # Look up the IP address in a City database.
108
- #
109
- # @param ip_address [String] a string in the standard notation. It may be
110
- # IPv4 or IPv6.
111
- #
112
- # @return [MaxMind::GeoIP2::Model::City]
113
- #
114
- # @raise [ArgumentError] if used against a non-City database or if you
115
- # attempt to look up an IPv6 address in an IPv4 only database.
116
- #
117
- # @raise [AddressNotFoundError] if the IP address is not found in the
118
- # database.
119
- #
120
- # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
121
- # corrupt.
122
- def city(ip_address)
123
- model_for(Model::City, 'city', 'City', ip_address)
124
- end
77
+ locales = ['en'] if locales.nil? || locales.empty?
125
78
 
126
- # Look up the IP address in a Connection Type database.
127
- #
128
- # @param ip_address [String] a string in the standard notation. It may be
129
- # IPv4 or IPv6.
130
- #
131
- # @return [MaxMind::GeoIP2::Model::ConnectionType]
132
- #
133
- # @raise [ArgumentError] if used against a non-Connection Type database or if
134
- # you attempt to look up an IPv6 address in an IPv4 only database.
135
- #
136
- # @raise [AddressNotFoundError] if the IP address is not found in the
137
- # database.
138
- #
139
- # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
140
- # corrupt.
141
- def connection_type(ip_address)
142
- flat_model_for(
143
- Model::ConnectionType,
144
- 'connection_type',
145
- 'GeoIP2-Connection-Type',
146
- ip_address,
147
- )
148
- end
79
+ options = {}
80
+ options[:mode] = mode if !mode.nil?
81
+ @reader = MaxMind::DB.new(database, options)
149
82
 
150
- # Look up the IP address in a Country database.
151
- #
152
- # @param ip_address [String] a string in the standard notation. It may be
153
- # IPv4 or IPv6.
154
- #
155
- # @return [MaxMind::GeoIP2::Model::Country]
156
- #
157
- # @raise [ArgumentError] if used against a non-Country database or if you
158
- # attempt to look up an IPv6 address in an IPv4 only database.
159
- #
160
- # @raise [AddressNotFoundError] if the IP address is not found in the
161
- # database.
162
- #
163
- # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
164
- # corrupt.
165
- def country(ip_address)
166
- model_for(Model::Country, 'country', 'Country', ip_address)
167
- end
83
+ @type = @reader.metadata.database_type
168
84
 
169
- # Look up the IP address in a Domain database.
170
- #
171
- # @param ip_address [String] a string in the standard notation. It may be
172
- # IPv4 or IPv6.
173
- #
174
- # @return [MaxMind::GeoIP2::Model::Domain]
175
- #
176
- # @raise [ArgumentError] if used against a non-Domain database or if you
177
- # attempt to look up an IPv6 address in an IPv4 only database.
178
- #
179
- # @raise [AddressNotFoundError] if the IP address is not found in the
180
- # database.
181
- #
182
- # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
183
- # corrupt.
184
- def domain(ip_address)
185
- flat_model_for(Model::Domain, 'domain', 'GeoIP2-Domain', ip_address)
186
- end
85
+ @locales = locales
86
+ end
87
+ # rubocop:enable Metrics/CyclomaticComplexity
88
+ # rubocop:enable Metrics/PerceivedComplexity
187
89
 
188
- # Look up the IP address in an Enterprise database.
189
- #
190
- # @param ip_address [String] a string in the standard notation. It may be
191
- # IPv4 or IPv6.
192
- #
193
- # @return [MaxMind::GeoIP2::Model::Enterprise]
194
- #
195
- # @raise [ArgumentError] if used against a non-Enterprise database or if
196
- # you attempt to look up an IPv6 address in an IPv4 only database.
197
- #
198
- # @raise [AddressNotFoundError] if the IP address is not found in the
199
- # database.
200
- #
201
- # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
202
- # corrupt.
203
- def enterprise(ip_address)
204
- model_for(Model::Enterprise, 'enterprise', 'Enterprise', ip_address)
205
- end
90
+ # Look up the IP address in the database.
91
+ #
92
+ # @param ip_address [String] a string in the standard notation. It may be
93
+ # IPv4 or IPv6.
94
+ #
95
+ # @return [MaxMind::GeoIP2::Model::AnonymousIP]
96
+ #
97
+ # @raise [ArgumentError] if used against a non-Anonymous IP database or if
98
+ # you attempt to look up an IPv6 address in an IPv4 only database.
99
+ #
100
+ # @raise [AddressNotFoundError] if the IP address is not found in the
101
+ # database.
102
+ #
103
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
104
+ # corrupt.
105
+ def anonymous_ip(ip_address)
106
+ flat_model_for(
107
+ Model::AnonymousIP,
108
+ 'anonymous_ip',
109
+ 'GeoIP2-Anonymous-IP',
110
+ ip_address,
111
+ )
112
+ end
206
113
 
207
- # Look up the IP address in an ISP database.
208
- #
209
- # @param ip_address [String] a string in the standard notation. It may be
210
- # IPv4 or IPv6.
211
- #
212
- # @return [MaxMind::GeoIP2::Model::ISP]
213
- #
214
- # @raise [ArgumentError] if used against a non-ISP database or if you
215
- # attempt to look up an IPv6 address in an IPv4 only database.
216
- #
217
- # @raise [AddressNotFoundError] if the IP address is not found in the
218
- # database.
219
- #
220
- # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
221
- # corrupt.
222
- def isp(ip_address)
223
- flat_model_for(Model::ISP, 'isp', 'GeoIP2-ISP', ip_address)
224
- end
114
+ # Look up the IP address in an ASN database.
115
+ #
116
+ # @param ip_address [String] a string in the standard notation. It may be
117
+ # IPv4 or IPv6.
118
+ #
119
+ # @return [MaxMind::GeoIP2::Model::ASN]
120
+ #
121
+ # @raise [ArgumentError] if used against a non-ASN database or if you
122
+ # attempt to look up an IPv6 address in an IPv4 only database.
123
+ #
124
+ # @raise [AddressNotFoundError] if the IP address is not found in the
125
+ # database.
126
+ #
127
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
128
+ # corrupt.
129
+ def asn(ip_address)
130
+ flat_model_for(Model::ASN, 'asn', 'GeoLite2-ASN', ip_address)
131
+ end
225
132
 
226
- # Return the metadata associated with the database.
227
- #
228
- # @return [MaxMind::DB::Metadata]
229
- def metadata
230
- @reader.metadata
231
- end
133
+ # Look up the IP address in a City database.
134
+ #
135
+ # @param ip_address [String] a string in the standard notation. It may be
136
+ # IPv4 or IPv6.
137
+ #
138
+ # @return [MaxMind::GeoIP2::Model::City]
139
+ #
140
+ # @raise [ArgumentError] if used against a non-City database or if you
141
+ # attempt to look up an IPv6 address in an IPv4 only database.
142
+ #
143
+ # @raise [AddressNotFoundError] if the IP address is not found in the
144
+ # database.
145
+ #
146
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
147
+ # corrupt.
148
+ def city(ip_address)
149
+ model_for(Model::City, 'city', 'City', ip_address)
150
+ end
232
151
 
233
- # Close the Reader and return resources to the system.
234
- #
235
- # @return [void]
236
- def close
237
- @reader.close
238
- end
152
+ # Look up the IP address in a Connection Type database.
153
+ #
154
+ # @param ip_address [String] a string in the standard notation. It may be
155
+ # IPv4 or IPv6.
156
+ #
157
+ # @return [MaxMind::GeoIP2::Model::ConnectionType]
158
+ #
159
+ # @raise [ArgumentError] if used against a non-Connection Type database or if
160
+ # you attempt to look up an IPv6 address in an IPv4 only database.
161
+ #
162
+ # @raise [AddressNotFoundError] if the IP address is not found in the
163
+ # database.
164
+ #
165
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
166
+ # corrupt.
167
+ def connection_type(ip_address)
168
+ flat_model_for(
169
+ Model::ConnectionType,
170
+ 'connection_type',
171
+ 'GeoIP2-Connection-Type',
172
+ ip_address,
173
+ )
174
+ end
239
175
 
240
- private
176
+ # Look up the IP address in a Country database.
177
+ #
178
+ # @param ip_address [String] a string in the standard notation. It may be
179
+ # IPv4 or IPv6.
180
+ #
181
+ # @return [MaxMind::GeoIP2::Model::Country]
182
+ #
183
+ # @raise [ArgumentError] if used against a non-Country database or if you
184
+ # attempt to look up an IPv6 address in an IPv4 only database.
185
+ #
186
+ # @raise [AddressNotFoundError] if the IP address is not found in the
187
+ # database.
188
+ #
189
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
190
+ # corrupt.
191
+ def country(ip_address)
192
+ model_for(Model::Country, 'country', 'Country', ip_address)
193
+ end
241
194
 
242
- def model_for(model_class, method, type, ip_address)
243
- record, prefix_length = get_record(method, type, ip_address)
195
+ # Look up the IP address in a Domain database.
196
+ #
197
+ # @param ip_address [String] a string in the standard notation. It may be
198
+ # IPv4 or IPv6.
199
+ #
200
+ # @return [MaxMind::GeoIP2::Model::Domain]
201
+ #
202
+ # @raise [ArgumentError] if used against a non-Domain database or if you
203
+ # attempt to look up an IPv6 address in an IPv4 only database.
204
+ #
205
+ # @raise [AddressNotFoundError] if the IP address is not found in the
206
+ # database.
207
+ #
208
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
209
+ # corrupt.
210
+ def domain(ip_address)
211
+ flat_model_for(Model::Domain, 'domain', 'GeoIP2-Domain', ip_address)
212
+ end
244
213
 
245
- record['traits'] = {} if !record.key?('traits')
246
- record['traits']['ip_address'] = ip_address
247
- record['traits']['prefix_length'] = prefix_length
214
+ # Look up the IP address in an Enterprise database.
215
+ #
216
+ # @param ip_address [String] a string in the standard notation. It may be
217
+ # IPv4 or IPv6.
218
+ #
219
+ # @return [MaxMind::GeoIP2::Model::Enterprise]
220
+ #
221
+ # @raise [ArgumentError] if used against a non-Enterprise database or if
222
+ # you attempt to look up an IPv6 address in an IPv4 only database.
223
+ #
224
+ # @raise [AddressNotFoundError] if the IP address is not found in the
225
+ # database.
226
+ #
227
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
228
+ # corrupt.
229
+ def enterprise(ip_address)
230
+ model_for(Model::Enterprise, 'enterprise', 'Enterprise', ip_address)
231
+ end
248
232
 
249
- model_class.new(record, @locales)
250
- end
233
+ # Look up the IP address in an ISP database.
234
+ #
235
+ # @param ip_address [String] a string in the standard notation. It may be
236
+ # IPv4 or IPv6.
237
+ #
238
+ # @return [MaxMind::GeoIP2::Model::ISP]
239
+ #
240
+ # @raise [ArgumentError] if used against a non-ISP database or if you
241
+ # attempt to look up an IPv6 address in an IPv4 only database.
242
+ #
243
+ # @raise [AddressNotFoundError] if the IP address is not found in the
244
+ # database.
245
+ #
246
+ # @raise [MaxMind::DB::InvalidDatabaseError] if the database appears
247
+ # corrupt.
248
+ def isp(ip_address)
249
+ flat_model_for(Model::ISP, 'isp', 'GeoIP2-ISP', ip_address)
250
+ end
251
251
 
252
- def get_record(method, type, ip_address)
253
- if !@type.include?(type)
254
- raise ArgumentError,
255
- "The #{method} method cannot be used with the #{@type} database."
252
+ # Return the metadata associated with the database.
253
+ #
254
+ # @return [MaxMind::DB::Metadata]
255
+ def metadata
256
+ @reader.metadata
256
257
  end
257
258
 
258
- record, prefix_length = @reader.get_with_prefix_length(ip_address)
259
+ # Close the Reader and return resources to the system.
260
+ #
261
+ # @return [void]
262
+ def close
263
+ @reader.close
264
+ end
259
265
 
260
- if record.nil?
261
- raise AddressNotFoundError,
262
- "The address #{ip_address} is not in the database."
266
+ private
267
+
268
+ def model_for(model_class, method, type, ip_address)
269
+ record, prefix_length = get_record(method, type, ip_address)
270
+
271
+ record['traits'] = {} if !record.key?('traits')
272
+ record['traits']['ip_address'] = ip_address
273
+ record['traits']['prefix_length'] = prefix_length
274
+
275
+ model_class.new(record, @locales)
263
276
  end
264
277
 
265
- [record, prefix_length]
266
- end
278
+ def get_record(method, type, ip_address)
279
+ if !@type.include?(type)
280
+ raise ArgumentError,
281
+ "The #{method} method cannot be used with the #{@type} database."
282
+ end
267
283
 
268
- def flat_model_for(model_class, method, type, ip_address)
269
- record, prefix_length = get_record(method, type, ip_address)
284
+ record, prefix_length = @reader.get_with_prefix_length(ip_address)
270
285
 
271
- record['ip_address'] = ip_address
272
- record['prefix_length'] = prefix_length
286
+ if record.nil?
287
+ raise AddressNotFoundError,
288
+ "The address #{ip_address} is not in the database."
289
+ end
273
290
 
274
- model_class.new(record)
291
+ [record, prefix_length]
292
+ end
293
+
294
+ def flat_model_for(model_class, method, type, ip_address)
295
+ record, prefix_length = get_record(method, type, ip_address)
296
+
297
+ record['ip_address'] = ip_address
298
+ record['prefix_length'] = prefix_length
299
+
300
+ model_class.new(record)
301
+ end
275
302
  end
276
303
  end
277
304
  end