maxmind-db 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +15 -0
- data/Gemfile +1 -4
- data/README.dev.md +17 -5
- data/README.md +2 -11
- data/bin/mmdb-benchmark.rb +3 -3
- data/lib/maxmind/db/decoder.rb +7 -2
- data/lib/maxmind/db/errors.rb +1 -1
- data/lib/maxmind/db/file_reader.rb +32 -13
- data/lib/maxmind/db/memory_reader.rb +4 -4
- data/lib/maxmind/db/metadata.rb +28 -2
- data/lib/maxmind/db.rb +43 -40
- data/maxmind-db.gemspec +10 -4
- data/test/data/LICENSE +4 -0
- data/test/data/MaxMind-DB-spec.md +574 -0
- data/test/data/README.md +4 -0
- data/test/data/bad-data/README.md +7 -0
- data/test/data/bad-data/libmaxminddb/libmaxminddb-offset-integer-overflow.mmdb +0 -0
- data/test/data/bad-data/maxminddb-golang/cyclic-data-structure.mmdb +0 -0
- data/test/data/bad-data/maxminddb-golang/invalid-bytes-length.mmdb +1 -0
- data/test/data/bad-data/maxminddb-golang/invalid-data-record-offset.mmdb +0 -0
- data/test/data/bad-data/maxminddb-golang/invalid-map-key-length.mmdb +0 -0
- data/test/data/bad-data/maxminddb-golang/invalid-string-length.mmdb +1 -0
- data/test/data/bad-data/maxminddb-golang/metadata-is-an-uint128.mmdb +1 -0
- data/test/data/bad-data/maxminddb-golang/unexpected-bytes.mmdb +0 -0
- data/test/data/bad-data/maxminddb-python/bad-unicode-in-map-key.mmdb +0 -0
- data/test/data/perltidyrc +12 -0
- data/test/data/source-data/GeoIP2-Anonymous-IP-Test.json +49 -0
- data/test/data/source-data/GeoIP2-City-Test.json +12885 -0
- data/test/data/source-data/GeoIP2-Connection-Type-Test.json +122 -0
- data/test/data/source-data/GeoIP2-Country-Test.json +15904 -0
- data/test/data/source-data/GeoIP2-DensityIncome-Test.json +14 -0
- data/test/data/source-data/GeoIP2-Domain-Test.json +452 -0
- data/test/data/source-data/GeoIP2-Enterprise-Test.json +745 -0
- data/test/data/source-data/GeoIP2-ISP-Test.json +12605 -0
- data/test/data/source-data/GeoIP2-Precision-Enterprise-Test.json +2205 -0
- data/test/data/source-data/GeoIP2-Static-IP-Score-Test.json +2132 -0
- data/test/data/source-data/GeoIP2-User-Count-Test.json +2837 -0
- data/test/data/source-data/GeoLite2-ASN-Test.json +4120 -0
- data/test/data/source-data/GeoLite2-City-Test.json +12804 -0
- data/test/data/source-data/GeoLite2-Country-Test.json +11280 -0
- data/test/data/source-data/README +15 -0
- data/test/data/test-data/GeoIP2-Anonymous-IP-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-City-Test-Broken-Double-Format.mmdb +0 -0
- data/test/data/test-data/GeoIP2-City-Test-Invalid-Node-Count.mmdb +0 -0
- data/test/data/test-data/GeoIP2-City-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-Connection-Type-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-Country-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-DensityIncome-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-Domain-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-Enterprise-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-ISP-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-Precision-Enterprise-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-Static-IP-Score-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-User-Count-Test.mmdb +0 -0
- data/test/data/test-data/GeoLite2-ASN-Test.mmdb +0 -0
- data/test/data/test-data/GeoLite2-City-Test.mmdb +0 -0
- data/test/data/test-data/GeoLite2-Country-Test.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-no-ipv4-search-tree.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-string-value-entries.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-broken-pointers-24.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-broken-search-tree-24.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-decoder.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-ipv4-24.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-ipv4-28.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-ipv4-32.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-ipv6-24.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-ipv6-28.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-ipv6-32.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-metadata-pointers.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-mixed-24.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-mixed-28.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-mixed-32.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-nested.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-pointer-decoder.mmdb +0 -0
- data/test/data/test-data/README.md +26 -0
- data/test/data/test-data/maps-with-pointers.raw +0 -0
- data/test/data/test-data/write-test-data.pl +695 -0
- data/test/data/tidyall.ini +5 -0
- data/test/mmdb_util.rb +1 -1
- data/test/test_decoder.rb +7 -7
- data/test/test_reader.rb +36 -14
- metadata +130 -9
- data/Gemfile.lock +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d5705dca32ee40fdadd07a1f6abc8a0ff56e23b699ecb9ba159344a9325c8456
|
4
|
+
data.tar.gz: d71304945c1c09f3af09a85b03dbbcf8cbeb4652456441a7f6978b2cb9db6adc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8c1a541fcf270945c34254e2e5817ac52864f6cea427d223cb4b5c9c4036afdc61380954462fe063beeacd3407507a647eff776ab8913a561eef6eed71a6730
|
7
|
+
data.tar.gz: 70c1967f07e22885938b7fb1e9cbd0a73c9d4f3efab144a6aa4c2e40bac81ce8445d2702ad51d2b32e028a6eef053f132542d9d9c1086030d224575a4bb39e64
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.2.0 (2023-11-22)
|
4
|
+
|
5
|
+
* Ruby 2.4 is no longer supported. If you're using Ruby 2.4, please use
|
6
|
+
version 1.1.1 of this gem.
|
7
|
+
* `Object#respond_to?` is no longer called on every read. Pull request by
|
8
|
+
Jean byroot Boussier. GitHub #65.
|
9
|
+
* The `get` and `get_prefix_length` methods now accept the IP addresses as
|
10
|
+
`IPAddr` objects. Strings are still accepted too. Pull request by Eddie
|
11
|
+
Lebow. GitHub #69.
|
12
|
+
|
13
|
+
## 1.1.1 (2020-06-23)
|
14
|
+
|
15
|
+
* Fixed the memory reader's inspect method to no longer attempt to modify a
|
16
|
+
frozen string. Pull request by Tietew. GitHub #35.
|
17
|
+
|
3
18
|
## 1.1.0 (2020-01-08)
|
4
19
|
|
5
20
|
* The method `get_with_prefix_length` was added. This method returns both
|
data/Gemfile
CHANGED
data/README.dev.md
CHANGED
@@ -1,14 +1,22 @@
|
|
1
1
|
# How to release
|
2
|
-
*
|
3
|
-
*
|
2
|
+
* Ensure tests pass: `rake`
|
3
|
+
* Update changelog: Set version and release date
|
4
|
+
* Set version in `maxmind-db.gemspec`
|
5
|
+
* Add them: `git add -p`
|
6
|
+
* Create a branch e.g. `horgh/release` and switch to it.
|
7
|
+
* `main` is protected.
|
4
8
|
* Commit: `git commit -m v1.0.0`
|
5
9
|
* Tag: `git tag -a v1.0.0 -m v1.0.0`
|
6
10
|
* Clean up to be sure nothing stray gets into gem: `git clean -dxff`
|
7
11
|
* Create `.gem` file: `gem build maxmind-db.gemspec`
|
8
12
|
* Complete prerequisites (see below)
|
13
|
+
* You only need to do this once. You can tell if this is necessary if you
|
14
|
+
are lacking `:rubygems_api_key` in `~/.local/share/gem/credentials`
|
15
|
+
(previously `~/.gem/credentials`)
|
9
16
|
* Upload to rubygems.org: `gem push maxmind-db-1.0.0.gem`
|
10
17
|
* Push: `git push`
|
11
18
|
* Push tag: `git push --tags`
|
19
|
+
* Make a PR and get it merged.
|
12
20
|
* Double check it looks okay at https://rubygems.org/gems/maxmind-db and
|
13
21
|
https://www.rubydoc.info/gems/maxmind-db
|
14
22
|
|
@@ -18,7 +26,7 @@
|
|
18
26
|
## Step 1
|
19
27
|
Sign up for an account at rubygems.org if you don't have one.
|
20
28
|
|
21
|
-
Enable multi factor authentication.
|
29
|
+
Enable multi factor authentication (for both UI and API).
|
22
30
|
|
23
31
|
|
24
32
|
## Step 2
|
@@ -29,5 +37,9 @@ They do this by using the `gem owner` command
|
|
29
37
|
|
30
38
|
|
31
39
|
## Step 3
|
32
|
-
|
33
|
-
|
40
|
+
Run `gem signin`. This will prompt you for your username and password, and
|
41
|
+
then create an API key for you. Select the scopes `index_rubygems` and
|
42
|
+
`push_rubygem` (I'm not sure the former is required, but anyway).
|
43
|
+
|
44
|
+
Note you may need an up to date version of rubygems to do this as I believe
|
45
|
+
support for API keys like this is a newer addition.
|
data/README.md
CHANGED
@@ -6,20 +6,12 @@ This is the Ruby API for reading [MaxMind
|
|
6
6
|
DB](https://maxmind.github.io/MaxMind-DB/) files. MaxMind DB is a binary
|
7
7
|
file format that stores data indexed by IP address subnets (IPv4 or IPv6).
|
8
8
|
|
9
|
-
|
10
9
|
## Installation
|
11
10
|
|
12
11
|
```
|
13
12
|
gem install maxmind-db
|
14
13
|
```
|
15
14
|
|
16
|
-
Or from source:
|
17
|
-
|
18
|
-
```
|
19
|
-
gem build maxmind-db.spec
|
20
|
-
gem install ./maxmind-db-xxx.gem
|
21
|
-
```
|
22
|
-
|
23
15
|
## Usage
|
24
16
|
|
25
17
|
```ruby
|
@@ -43,8 +35,7 @@ For more information see the
|
|
43
35
|
|
44
36
|
## Requirements
|
45
37
|
|
46
|
-
This code requires Ruby version 2.
|
47
|
-
are not supported.
|
38
|
+
This code requires Ruby version 2.5 or higher.
|
48
39
|
|
49
40
|
## Contributing
|
50
41
|
|
@@ -65,7 +56,7 @@ This library uses [Semantic Versioning](https://semver.org/).
|
|
65
56
|
|
66
57
|
## Copyright and License
|
67
58
|
|
68
|
-
This software is Copyright (c) 2018 -
|
59
|
+
This software is Copyright (c) 2018 - 2023 by MaxMind, Inc.
|
69
60
|
|
70
61
|
This is free software, licensed under the [Apache License, Version
|
71
62
|
2.0](LICENSE-APACHE) or the [MIT License](LICENSE-MIT), at your option.
|
data/bin/mmdb-benchmark.rb
CHANGED
@@ -29,9 +29,9 @@ end
|
|
29
29
|
|
30
30
|
def print_usage
|
31
31
|
# rubocop:disable Style/StderrPuts
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
$stderr.puts "Usage: #{$PROGRAM_NAME} <MMDB file> <IP file>"
|
33
|
+
$stderr.puts
|
34
|
+
$stderr.puts 'Benchmark by reading IPs from the IP file and looking up each one in the MMDB file.'
|
35
35
|
# rubocop:enable Style/StderrPuts
|
36
36
|
end
|
37
37
|
|
data/lib/maxmind/db/decoder.rb
CHANGED
@@ -2,14 +2,18 @@
|
|
2
2
|
|
3
3
|
require 'maxmind/db/errors'
|
4
4
|
|
5
|
-
module MaxMind
|
5
|
+
module MaxMind
|
6
6
|
class DB
|
7
7
|
# +Decoder+ decodes a {MaxMind DB}[https://maxmind.github.io/MaxMind-DB/]
|
8
8
|
# data section.
|
9
9
|
#
|
10
10
|
# Typically you will interact with this class through a Reader rather than
|
11
11
|
# directly.
|
12
|
-
|
12
|
+
#
|
13
|
+
# @!visibility private
|
14
|
+
class Decoder
|
15
|
+
# rubocop:disable Style/OptionalBooleanParameter
|
16
|
+
|
13
17
|
# Create a +Decoder+.
|
14
18
|
#
|
15
19
|
# +io+ is the DB. It must provide a +read+ method. It must be opened in
|
@@ -26,6 +30,7 @@ module MaxMind # :nodoc:
|
|
26
30
|
@pointer_base = pointer_base
|
27
31
|
@pointer_test = pointer_test
|
28
32
|
end
|
33
|
+
# rubocop:enable Style/OptionalBooleanParameter
|
29
34
|
|
30
35
|
private
|
31
36
|
|
data/lib/maxmind/db/errors.rb
CHANGED
@@ -2,13 +2,40 @@
|
|
2
2
|
|
3
3
|
require 'maxmind/db/errors'
|
4
4
|
|
5
|
-
module MaxMind
|
5
|
+
module MaxMind
|
6
6
|
class DB
|
7
|
-
|
7
|
+
# @!visibility private
|
8
|
+
class FileReader
|
9
|
+
if ::File.method_defined?(:pread)
|
10
|
+
PReadFile = ::File
|
11
|
+
else
|
12
|
+
# For Windows support
|
13
|
+
class PReadFile
|
14
|
+
def initialize(filename, mode)
|
15
|
+
@mutex = Mutex.new
|
16
|
+
@file = File.new(filename, mode)
|
17
|
+
end
|
18
|
+
|
19
|
+
def size
|
20
|
+
@file.size
|
21
|
+
end
|
22
|
+
|
23
|
+
def close
|
24
|
+
@file.close
|
25
|
+
end
|
26
|
+
|
27
|
+
def pread(size, offset)
|
28
|
+
@mutex.synchronize do
|
29
|
+
@file.seek(offset, IO::SEEK_SET)
|
30
|
+
@file.read(size)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
8
36
|
def initialize(filename)
|
9
|
-
@fh =
|
37
|
+
@fh = PReadFile.new(filename, 'rb')
|
10
38
|
@size = @fh.size
|
11
|
-
@mutex = Mutex.new
|
12
39
|
end
|
13
40
|
|
14
41
|
attr_reader :size
|
@@ -20,15 +47,7 @@ module MaxMind # :nodoc:
|
|
20
47
|
def read(offset, size)
|
21
48
|
return ''.b if size == 0
|
22
49
|
|
23
|
-
|
24
|
-
if @fh.respond_to?(:pread)
|
25
|
-
buf = @fh.pread(size, offset)
|
26
|
-
else
|
27
|
-
@mutex.synchronize do
|
28
|
-
@fh.seek(offset, IO::SEEK_SET)
|
29
|
-
buf = @fh.read(size)
|
30
|
-
end
|
31
|
-
end
|
50
|
+
buf = @fh.pread(size, offset)
|
32
51
|
|
33
52
|
raise InvalidDatabaseError, 'The MaxMind DB file contains bad data' if buf.nil? || buf.length != size
|
34
53
|
|
@@ -1,8 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module MaxMind
|
3
|
+
module MaxMind
|
4
4
|
class DB
|
5
|
-
|
5
|
+
# @!visibility private
|
6
|
+
class MemoryReader
|
6
7
|
def initialize(filename, options = {})
|
7
8
|
if options[:is_buffer]
|
8
9
|
@buf = filename
|
@@ -18,8 +19,7 @@ module MaxMind # :nodoc:
|
|
18
19
|
|
19
20
|
# Override to not show @buf in inspect to avoid showing it in irb.
|
20
21
|
def inspect
|
21
|
-
|
22
|
-
s << '@size=' << @size.inspect << '>'
|
22
|
+
"#<#{self.class.name}:0x#{self.class.object_id.to_s(16)}, @size=#{@size.inspect}>"
|
23
23
|
end
|
24
24
|
|
25
25
|
def close; end
|
data/lib/maxmind/db/metadata.rb
CHANGED
@@ -1,42 +1,64 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module MaxMind
|
3
|
+
module MaxMind
|
4
4
|
class DB
|
5
5
|
# Metadata holds metadata about a {MaxMind
|
6
|
-
# DB}[https://maxmind.github.io/MaxMind-DB/] file.
|
6
|
+
# DB}[https://maxmind.github.io/MaxMind-DB/] file. See
|
7
|
+
# https://maxmind.github.io/MaxMind-DB/#database-metadata for the
|
8
|
+
# specification.
|
7
9
|
class Metadata
|
8
10
|
# The number of nodes in the database.
|
11
|
+
#
|
12
|
+
# @return [Integer]
|
9
13
|
attr_reader :node_count
|
10
14
|
|
11
15
|
# The bit size of a record in the search tree.
|
16
|
+
#
|
17
|
+
# @return [Integer]
|
12
18
|
attr_reader :record_size
|
13
19
|
|
14
20
|
# The IP version of the data in the database. A value of 4 means the
|
15
21
|
# database only supports IPv4. A database with a value of 6 may support
|
16
22
|
# both IPv4 and IPv6 lookups.
|
23
|
+
#
|
24
|
+
# @return [Integer]
|
17
25
|
attr_reader :ip_version
|
18
26
|
|
19
27
|
# A string identifying the database type. e.g., "GeoIP2-City".
|
28
|
+
#
|
29
|
+
# @return [String]
|
20
30
|
attr_reader :database_type
|
21
31
|
|
22
32
|
# An array of locale codes supported by the database.
|
33
|
+
#
|
34
|
+
# @return [Array<String>]
|
23
35
|
attr_reader :languages
|
24
36
|
|
25
37
|
# The major version number of the binary format used when creating the
|
26
38
|
# database.
|
39
|
+
#
|
40
|
+
# @return [Integer]
|
27
41
|
attr_reader :binary_format_major_version
|
28
42
|
|
29
43
|
# The minor version number of the binary format used when creating the
|
30
44
|
# database.
|
45
|
+
#
|
46
|
+
# @return [Integer]
|
31
47
|
attr_reader :binary_format_minor_version
|
32
48
|
|
33
49
|
# The Unix epoch for the build time of the database.
|
50
|
+
#
|
51
|
+
# @return [Integer]
|
34
52
|
attr_reader :build_epoch
|
35
53
|
|
36
54
|
# A hash from locales to text descriptions of the database.
|
55
|
+
#
|
56
|
+
# @return [Hash<String, String>]
|
37
57
|
attr_reader :description
|
38
58
|
|
39
59
|
# +m+ is a hash representing the metadata map.
|
60
|
+
#
|
61
|
+
# @!visibility private
|
40
62
|
def initialize(map)
|
41
63
|
@node_count = map['node_count']
|
42
64
|
@record_size = map['record_size']
|
@@ -50,11 +72,15 @@ module MaxMind # :nodoc:
|
|
50
72
|
end
|
51
73
|
|
52
74
|
# The size of a node in bytes.
|
75
|
+
#
|
76
|
+
# @return [Integer]
|
53
77
|
def node_byte_size
|
54
78
|
@record_size / 4
|
55
79
|
end
|
56
80
|
|
57
81
|
# The size of the search tree in bytes.
|
82
|
+
#
|
83
|
+
# @return [Integer]
|
58
84
|
def search_tree_size
|
59
85
|
@node_count * node_byte_size
|
60
86
|
end
|
data/lib/maxmind/db.rb
CHANGED
@@ -3,11 +3,11 @@
|
|
3
3
|
require 'ipaddr'
|
4
4
|
require 'maxmind/db/decoder'
|
5
5
|
require 'maxmind/db/errors'
|
6
|
-
require 'maxmind/db/file_reader
|
7
|
-
require 'maxmind/db/memory_reader
|
8
|
-
require 'maxmind/db/metadata
|
6
|
+
require 'maxmind/db/file_reader'
|
7
|
+
require 'maxmind/db/memory_reader'
|
8
|
+
require 'maxmind/db/metadata'
|
9
9
|
|
10
|
-
module MaxMind
|
10
|
+
module MaxMind
|
11
11
|
# DB provides a way to read {MaxMind DB
|
12
12
|
# files}[https://maxmind.github.io/MaxMind-DB/].
|
13
13
|
#
|
@@ -31,11 +31,6 @@ module MaxMind # :nodoc:
|
|
31
31
|
# end
|
32
32
|
#
|
33
33
|
# reader.close
|
34
|
-
#
|
35
|
-
# == Exceptions
|
36
|
-
#
|
37
|
-
# DB raises an InvalidDatabaseError if the database is corrupt or invalid. It
|
38
|
-
# can raise other exceptions, such as ArgumentError, if other errors occur.
|
39
34
|
class DB
|
40
35
|
# Choose the default method to open the database. Currently the default is
|
41
36
|
# MODE_FILE.
|
@@ -47,7 +42,9 @@ module MaxMind # :nodoc:
|
|
47
42
|
MODE_MEMORY = :MODE_MEMORY
|
48
43
|
# Treat the database parameter as containing a database already read into
|
49
44
|
# memory. It must be a binary string. This primarily exists for testing.
|
50
|
-
|
45
|
+
#
|
46
|
+
# @!visibility private
|
47
|
+
MODE_PARAM_IS_BUFFER = :MODE_PARAM_IS_BUFFER
|
51
48
|
|
52
49
|
DATA_SECTION_SEPARATOR_SIZE = 16
|
53
50
|
private_constant :DATA_SECTION_SEPARATOR_SIZE
|
@@ -59,7 +56,9 @@ module MaxMind # :nodoc:
|
|
59
56
|
private_constant :METADATA_MAX_SIZE
|
60
57
|
|
61
58
|
# Return the metadata associated with the {MaxMind
|
62
|
-
# DB}[https://maxmind.github.io/MaxMind-DB/]
|
59
|
+
# DB}[https://maxmind.github.io/MaxMind-DB/]
|
60
|
+
#
|
61
|
+
# @return [MaxMind::DB::Metadata]
|
63
62
|
attr_reader :metadata
|
64
63
|
|
65
64
|
# Create a DB. A DB provides a way to read {MaxMind DB
|
@@ -70,20 +69,20 @@ module MaxMind # :nodoc:
|
|
70
69
|
# is safe to use after forking only if you use MODE_MEMORY or if your
|
71
70
|
# version of Ruby supports IO#pread.
|
72
71
|
#
|
73
|
-
#
|
72
|
+
# @param database [String] a path to a {MaxMind
|
73
|
+
# DB}[https://maxmind.github.io/MaxMind-DB/].
|
74
74
|
#
|
75
|
-
#
|
76
|
-
# DB
|
75
|
+
# @param options [Hash<Symbol, Symbol>] options controlling the behavior of
|
76
|
+
# the DB.
|
77
77
|
#
|
78
|
-
#
|
79
|
-
#
|
78
|
+
# @option options [Symbol] :mode Defines how to open the database. It may
|
79
|
+
# be one of MODE_AUTO, MODE_FILE, or MODE_MEMORY. If you don't provide
|
80
|
+
# one, DB uses MODE_AUTO. Refer to the definition of those constants for
|
81
|
+
# an explanation of their meaning.
|
80
82
|
#
|
81
|
-
#
|
83
|
+
# @raise [InvalidDatabaseError] if the database is corrupt or invalid.
|
82
84
|
#
|
83
|
-
# [
|
84
|
-
# MODE_FILE, or MODE_MEMORY. If you don't provide one, DB uses
|
85
|
-
# MODE_AUTO. Refer to the definition of those constants for an
|
86
|
-
# explanation of their meaning.
|
85
|
+
# @raise [ArgumentError] if the mode is invalid.
|
87
86
|
def initialize(database, options = {})
|
88
87
|
options[:mode] = MODE_AUTO unless options.key?(:mode)
|
89
88
|
|
@@ -125,37 +124,45 @@ module MaxMind # :nodoc:
|
|
125
124
|
end
|
126
125
|
end
|
127
126
|
|
128
|
-
# Return the record for the
|
127
|
+
# Return the record for the IP address in the {MaxMind
|
129
128
|
# DB}[https://maxmind.github.io/MaxMind-DB/]. The record can be one of
|
130
129
|
# several types and depends on the contents of the database.
|
131
130
|
#
|
132
|
-
# If no record is found for
|
131
|
+
# If no record is found for the IP address, +get+ returns +nil+.
|
132
|
+
#
|
133
|
+
# @param ip_address [String, IPAddr] IPv4 or IPv6 address.
|
133
134
|
#
|
134
|
-
#
|
135
|
+
# @raise [ArgumentError] if you attempt to look up an IPv6 address in an
|
136
|
+
# IPv4-only database.
|
135
137
|
#
|
136
|
-
#
|
137
|
-
#
|
138
|
+
# @raise [InvalidDatabaseError] if the database is corrupt or invalid.
|
139
|
+
#
|
140
|
+
# @return [Object, nil]
|
138
141
|
def get(ip_address)
|
139
142
|
record, = get_with_prefix_length(ip_address)
|
140
143
|
|
141
144
|
record
|
142
145
|
end
|
143
146
|
|
144
|
-
# Return an array containing the record for the
|
147
|
+
# Return an array containing the record for the IP address in the
|
145
148
|
# {MaxMind DB}[https://maxmind.github.io/MaxMind-DB/] and its associated
|
146
149
|
# network prefix length. The record can be one of several types and
|
147
150
|
# depends on the contents of the database.
|
148
151
|
#
|
149
|
-
# If no record is found for
|
152
|
+
# If no record is found for the IP address, the record will be +nil+ and
|
150
153
|
# the prefix length will be the value for the missing network.
|
151
154
|
#
|
152
|
-
#
|
153
|
-
#
|
155
|
+
# @param ip_address [String, IPAddr] IPv4 or IPv6 address.
|
156
|
+
#
|
157
|
+
# @raise [ArgumentError] if you attempt to look up an IPv6 address in an
|
158
|
+
# IPv4-only database.
|
159
|
+
#
|
160
|
+
# @raise [InvalidDatabaseError] if the database is corrupt or invalid.
|
154
161
|
#
|
155
|
-
#
|
156
|
-
# IPv6.
|
162
|
+
# @return [Array<(Object, Integer)>]
|
157
163
|
def get_with_prefix_length(ip_address)
|
158
|
-
ip = IPAddr.new(ip_address)
|
164
|
+
ip = ip_address.is_a?(IPAddr) ? ip_address : IPAddr.new(ip_address)
|
165
|
+
|
159
166
|
# We could check the IP has the correct prefix (32 or 128) but I do not
|
160
167
|
# for performance reasons.
|
161
168
|
|
@@ -192,7 +199,7 @@ module MaxMind # :nodoc:
|
|
192
199
|
break if depth >= bit_count || node >= node_count
|
193
200
|
|
194
201
|
c = packed[depth >> 3].ord
|
195
|
-
bit = 1 & (c >> 7 - (depth % 8))
|
202
|
+
bit = 1 & (c >> (7 - (depth % 8)))
|
196
203
|
node = read_node(node, bit)
|
197
204
|
depth += 1
|
198
205
|
end
|
@@ -221,8 +228,6 @@ module MaxMind # :nodoc:
|
|
221
228
|
|
222
229
|
# Read a record from the indicated node. Index indicates whether it's the
|
223
230
|
# left (0) or right (1) record.
|
224
|
-
#
|
225
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
226
231
|
def read_node(node_number, index)
|
227
232
|
base_offset = node_number * @node_byte_size
|
228
233
|
|
@@ -253,7 +258,6 @@ module MaxMind # :nodoc:
|
|
253
258
|
|
254
259
|
raise InvalidDatabaseError, "Unsupported record size: #{@record_size}"
|
255
260
|
end
|
256
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
257
261
|
|
258
262
|
def resolve_data_pointer(pointer)
|
259
263
|
offset_in_file = pointer - @node_count + @search_tree_size
|
@@ -268,7 +272,7 @@ module MaxMind # :nodoc:
|
|
268
272
|
end
|
269
273
|
|
270
274
|
def find_metadata_start
|
271
|
-
metadata_max_size = @size
|
275
|
+
metadata_max_size = [@size, METADATA_MAX_SIZE].min
|
272
276
|
|
273
277
|
stop_index = @size - metadata_max_size
|
274
278
|
index = @size - METADATA_START_MARKER_LENGTH
|
@@ -290,8 +294,7 @@ module MaxMind # :nodoc:
|
|
290
294
|
|
291
295
|
# Close the DB and return resources to the system.
|
292
296
|
#
|
293
|
-
#
|
294
|
-
# an error.
|
297
|
+
# @return [void]
|
295
298
|
def close
|
296
299
|
@io.close
|
297
300
|
end
|
data/maxmind-db.gemspec
CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |s|
|
|
5
5
|
s.files = Dir['**/*']
|
6
6
|
s.name = 'maxmind-db'
|
7
7
|
s.summary = 'A gem for reading MaxMind DB files.'
|
8
|
-
s.version = '1.
|
8
|
+
s.version = '1.2.0'
|
9
9
|
|
10
10
|
s.description = 'A gem for reading MaxMind DB files. MaxMind DB is a binary file format that stores data indexed by IP address subnets (IPv4 or IPv6).'
|
11
11
|
s.email = 'support@maxmind.com'
|
@@ -13,10 +13,16 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.licenses = ['Apache-2.0', 'MIT']
|
14
14
|
s.metadata = {
|
15
15
|
'bug_tracker_uri' => 'https://github.com/maxmind/MaxMind-DB-Reader-ruby/issues',
|
16
|
-
'changelog_uri' => 'https://github.com/maxmind/MaxMind-DB-Reader-ruby/blob/
|
17
|
-
'documentation_uri' => 'https://
|
16
|
+
'changelog_uri' => 'https://github.com/maxmind/MaxMind-DB-Reader-ruby/blob/main/CHANGELOG.md',
|
17
|
+
'documentation_uri' => 'https://www.rubydoc.info/gems/maxmind-db',
|
18
18
|
'homepage_uri' => 'https://github.com/maxmind/MaxMind-DB-Reader-ruby',
|
19
19
|
'source_code_uri' => 'https://github.com/maxmind/MaxMind-DB-Reader-ruby',
|
20
|
+
'rubygems_mfa_required' => 'true',
|
20
21
|
}
|
21
|
-
s.required_ruby_version = '>= 2.
|
22
|
+
s.required_ruby_version = '>= 2.5.0'
|
23
|
+
|
24
|
+
s.add_development_dependency 'minitest'
|
25
|
+
s.add_development_dependency 'rake'
|
26
|
+
s.add_development_dependency 'rubocop'
|
27
|
+
s.add_development_dependency 'rubocop-performance'
|
22
28
|
end
|
data/test/data/LICENSE
ADDED
@@ -0,0 +1,4 @@
|
|
1
|
+
This work is licensed under the Creative Commons Attribution-ShareAlike 3.0
|
2
|
+
Unported License. To view a copy of this license, visit
|
3
|
+
http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to Creative
|
4
|
+
Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.
|