maxmind-db 1.0.0 → 1.1.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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +13 -2
- data/Gemfile +8 -0
- data/Gemfile.lock +34 -0
- data/README.md +2 -2
- data/Rakefile +2 -0
- data/bin/mmdb-benchmark.rb +4 -1
- data/lib/maxmind/db.rb +49 -27
- data/lib/maxmind/db/decoder.rb +26 -26
- data/lib/maxmind/db/errors.rb +3 -1
- data/lib/maxmind/db/file_reader.rb +5 -3
- data/lib/maxmind/db/memory_reader.rb +3 -1
- data/lib/maxmind/db/metadata.rb +3 -1
- data/maxmind-db.gemspec +5 -2
- data/test/mmdb_util.rb +2 -0
- data/test/test_decoder.rb +2 -0
- data/test/test_reader.rb +117 -6
- metadata +7 -64
- data/test/data/LICENSE +0 -4
- data/test/data/MaxMind-DB-spec.md +0 -558
- data/test/data/MaxMind-DB-test-metadata-pointers.mmdb +0 -0
- data/test/data/README.md +0 -4
- data/test/data/bad-data/README.md +0 -7
- 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 +0 -1
- 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 +0 -1
- data/test/data/bad-data/maxminddb-golang/metadata-is-an-uint128.mmdb +0 -1
- data/test/data/bad-data/maxminddb-golang/unexpected-bytes.mmdb +0 -0
- data/test/data/perltidyrc +0 -12
- data/test/data/source-data/GeoIP2-Anonymous-IP-Test.json +0 -41
- data/test/data/source-data/GeoIP2-City-Test.json +0 -12852
- data/test/data/source-data/GeoIP2-Connection-Type-Test.json +0 -102
- data/test/data/source-data/GeoIP2-Country-Test.json +0 -11347
- data/test/data/source-data/GeoIP2-DensityIncome-Test.json +0 -14
- data/test/data/source-data/GeoIP2-Domain-Test.json +0 -452
- data/test/data/source-data/GeoIP2-Enterprise-Test.json +0 -673
- data/test/data/source-data/GeoIP2-ISP-Test.json +0 -12585
- data/test/data/source-data/GeoIP2-Precision-Enterprise-Test.json +0 -1598
- data/test/data/source-data/GeoIP2-User-Count-Test.json +0 -2824
- data/test/data/source-data/GeoLite2-ASN-Test.json +0 -37
- data/test/data/source-data/README +0 -15
- 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-User-Count-Test.mmdb +0 -0
- data/test/data/test-data/GeoLite2-ASN-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/README.md +0 -26
- data/test/data/test-data/maps-with-pointers.raw +0 -0
- data/test/data/test-data/write-test-data.pl +0 -620
- data/test/data/tidyall.ini +0 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: e8404a64573590d7a01fd9199ae1be5bb1892407
|
|
4
|
+
data.tar.gz: cfdec2ef12cae84fa914784b90c386d1006fdf47
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 263eff4235eadc529e14266772c3db95bc17950ebc7d73fbb3f5d20ee76f3b2f50035c97ad2e39454e5dbd65dd6093fc56f3a6dd3b8d91a69037b8e396986366
|
|
7
|
+
data.tar.gz: 8fe05ac4631539293ee2d1485fe7c1908858ef952d76e60e75d9f601f356263bb47928bc8dd670c2989df4437cb0d2a876869c662b1f4aab36d0e8a81ce19552
|
data/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 1.
|
|
3
|
+
## 1.1.0 (2020-01-08)
|
|
4
|
+
|
|
5
|
+
* The method `get_with_prefix_length` was added. This method returns both
|
|
6
|
+
the record and the network prefix length associated with the record in
|
|
7
|
+
the database.
|
|
8
|
+
* Simplified a check for whether to return early in the decoder. Pull
|
|
9
|
+
request by Ivan Palamarchuk. GitHub #12.
|
|
10
|
+
* Support for Ruby 2.3 was dropped since it is now end of life.
|
|
11
|
+
|
|
12
|
+
## 1.0.0 (2019-01-04)
|
|
13
|
+
|
|
4
14
|
* We no longer include the database's buffer in inspect output. This avoids
|
|
5
15
|
showing excessive output when creating a memory reader in irb. Reported
|
|
6
16
|
by Wojciech Wnętrzak. GitHub #6.
|
|
7
17
|
|
|
8
|
-
## 1.0.0.beta
|
|
18
|
+
## 1.0.0.beta (2018-12-24)
|
|
19
|
+
|
|
9
20
|
* Initial implementation.
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
GEM
|
|
2
|
+
remote: https://rubygems.org/
|
|
3
|
+
specs:
|
|
4
|
+
ast (2.4.0)
|
|
5
|
+
jaro_winkler (1.5.4)
|
|
6
|
+
minitest (5.13.0)
|
|
7
|
+
parallel (1.19.1)
|
|
8
|
+
parser (2.7.0.1)
|
|
9
|
+
ast (~> 2.4.0)
|
|
10
|
+
rainbow (3.0.0)
|
|
11
|
+
rake (13.0.1)
|
|
12
|
+
rubocop (0.79.0)
|
|
13
|
+
jaro_winkler (~> 1.5.1)
|
|
14
|
+
parallel (~> 1.10)
|
|
15
|
+
parser (>= 2.7.0.1)
|
|
16
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
17
|
+
ruby-progressbar (~> 1.7)
|
|
18
|
+
unicode-display_width (>= 1.4.0, < 1.7)
|
|
19
|
+
rubocop-performance (1.5.2)
|
|
20
|
+
rubocop (>= 0.71.0)
|
|
21
|
+
ruby-progressbar (1.10.1)
|
|
22
|
+
unicode-display_width (1.6.0)
|
|
23
|
+
|
|
24
|
+
PLATFORMS
|
|
25
|
+
ruby
|
|
26
|
+
|
|
27
|
+
DEPENDENCIES
|
|
28
|
+
minitest
|
|
29
|
+
rake
|
|
30
|
+
rubocop
|
|
31
|
+
rubocop-performance
|
|
32
|
+
|
|
33
|
+
BUNDLED WITH
|
|
34
|
+
2.0.1
|
data/README.md
CHANGED
|
@@ -43,7 +43,7 @@ For more information see the
|
|
|
43
43
|
|
|
44
44
|
## Requirements
|
|
45
45
|
|
|
46
|
-
This code requires Ruby version 2.
|
|
46
|
+
This code requires Ruby version 2.4 or higher. Older versions may work, but
|
|
47
47
|
are not supported.
|
|
48
48
|
|
|
49
49
|
## Contributing
|
|
@@ -65,7 +65,7 @@ This library uses [Semantic Versioning](https://semver.org/).
|
|
|
65
65
|
|
|
66
66
|
## Copyright and License
|
|
67
67
|
|
|
68
|
-
This software is Copyright (c) 2018 -
|
|
68
|
+
This software is Copyright (c) 2018 - 2020 by MaxMind, Inc.
|
|
69
69
|
|
|
70
70
|
This is free software, licensed under the [Apache License, Version
|
|
71
71
|
2.0](LICENSE-APACHE) or the [MIT License](LICENSE-MIT), at your option.
|
data/Rakefile
CHANGED
data/bin/mmdb-benchmark.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
require 'maxmind/db'
|
|
4
5
|
|
|
@@ -27,9 +28,11 @@ def parse_args
|
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
def print_usage
|
|
30
|
-
|
|
31
|
+
# rubocop:disable Style/StderrPuts
|
|
32
|
+
STDERR.puts "Usage: #{$PROGRAM_NAME} <MMDB file> <IP file>"
|
|
31
33
|
STDERR.puts
|
|
32
34
|
STDERR.puts 'Benchmark by reading IPs from the IP file and looking up each one in the MMDB file.'
|
|
35
|
+
# rubocop:enable Style/StderrPuts
|
|
33
36
|
end
|
|
34
37
|
|
|
35
38
|
def benchmark(reader, file)
|
data/lib/maxmind/db.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'ipaddr'
|
|
2
4
|
require 'maxmind/db/decoder'
|
|
3
5
|
require 'maxmind/db/errors'
|
|
@@ -7,9 +9,9 @@ require 'maxmind/db/metadata.rb'
|
|
|
7
9
|
|
|
8
10
|
module MaxMind # :nodoc:
|
|
9
11
|
# DB provides a way to read {MaxMind DB
|
|
10
|
-
# files}[
|
|
12
|
+
# files}[https://maxmind.github.io/MaxMind-DB/].
|
|
11
13
|
#
|
|
12
|
-
# {MaxMind DB}[
|
|
14
|
+
# {MaxMind DB}[https://maxmind.github.io/MaxMind-DB/] is a binary file format
|
|
13
15
|
# that stores data indexed by IP address subnets (IPv4 or IPv6).
|
|
14
16
|
#
|
|
15
17
|
# This class is a pure Ruby implementation of a reader for the format.
|
|
@@ -49,7 +51,7 @@ module MaxMind # :nodoc:
|
|
|
49
51
|
|
|
50
52
|
DATA_SECTION_SEPARATOR_SIZE = 16
|
|
51
53
|
private_constant :DATA_SECTION_SEPARATOR_SIZE
|
|
52
|
-
METADATA_START_MARKER = "\xAB\xCD\xEFMaxMind.com".
|
|
54
|
+
METADATA_START_MARKER = "\xAB\xCD\xEFMaxMind.com".b.freeze
|
|
53
55
|
private_constant :METADATA_START_MARKER
|
|
54
56
|
METADATA_START_MARKER_LENGTH = 14
|
|
55
57
|
private_constant :METADATA_START_MARKER_LENGTH
|
|
@@ -57,11 +59,11 @@ module MaxMind # :nodoc:
|
|
|
57
59
|
private_constant :METADATA_MAX_SIZE
|
|
58
60
|
|
|
59
61
|
# Return the metadata associated with the {MaxMind
|
|
60
|
-
# DB}[
|
|
62
|
+
# DB}[https://maxmind.github.io/MaxMind-DB/] as a Metadata object.
|
|
61
63
|
attr_reader :metadata
|
|
62
64
|
|
|
63
65
|
# Create a DB. A DB provides a way to read {MaxMind DB
|
|
64
|
-
# files}[
|
|
66
|
+
# files}[https://maxmind.github.io/MaxMind-DB/]. If you're performing
|
|
65
67
|
# multiple lookups, it's most efficient to create one DB and reuse it.
|
|
66
68
|
#
|
|
67
69
|
# Once created, the DB is safe to use for lookups from multiple threads. It
|
|
@@ -71,7 +73,7 @@ module MaxMind # :nodoc:
|
|
|
71
73
|
# Creating the DB may raise an exception if initialization fails.
|
|
72
74
|
#
|
|
73
75
|
# +database+ is a path to a {MaxMind
|
|
74
|
-
# DB}[
|
|
76
|
+
# DB}[https://maxmind.github.io/MaxMind-DB/].
|
|
75
77
|
#
|
|
76
78
|
# +options+ is an option hash where each key is a symbol. The options
|
|
77
79
|
# control the behaviour of the DB.
|
|
@@ -93,7 +95,7 @@ module MaxMind # :nodoc:
|
|
|
93
95
|
when MODE_PARAM_IS_BUFFER
|
|
94
96
|
@io = MemoryReader.new(database, is_buffer: true)
|
|
95
97
|
else
|
|
96
|
-
raise ArgumentError, 'Invalid mode'
|
|
98
|
+
raise ArgumentError, 'Invalid mode'
|
|
97
99
|
end
|
|
98
100
|
|
|
99
101
|
begin
|
|
@@ -124,7 +126,7 @@ module MaxMind # :nodoc:
|
|
|
124
126
|
end
|
|
125
127
|
|
|
126
128
|
# Return the record for the +ip_address+ in the {MaxMind
|
|
127
|
-
# DB}[
|
|
129
|
+
# DB}[https://maxmind.github.io/MaxMind-DB/]. The record can be one of
|
|
128
130
|
# several types and depends on the contents of the database.
|
|
129
131
|
#
|
|
130
132
|
# If no record is found for +ip_address+, +get+ returns +nil+.
|
|
@@ -134,6 +136,25 @@ module MaxMind # :nodoc:
|
|
|
134
136
|
# +ip_address+ is a string in the standard notation. It may be IPv4 or
|
|
135
137
|
# IPv6.
|
|
136
138
|
def get(ip_address)
|
|
139
|
+
record, = get_with_prefix_length(ip_address)
|
|
140
|
+
|
|
141
|
+
record
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Return an array containing the record for the +ip_address+ in the
|
|
145
|
+
# {MaxMind DB}[https://maxmind.github.io/MaxMind-DB/] and its associated
|
|
146
|
+
# network prefix length. The record can be one of several types and
|
|
147
|
+
# depends on the contents of the database.
|
|
148
|
+
#
|
|
149
|
+
# If no record is found for +ip_address+, the record will be +nil+ and
|
|
150
|
+
# the prefix length will be the value for the missing network.
|
|
151
|
+
#
|
|
152
|
+
# +get_with_prefix_length+ raises an exception if there is an error
|
|
153
|
+
# performing the lookup.
|
|
154
|
+
#
|
|
155
|
+
# +ip_address+ is a string in the standard notation. It may be IPv4 or
|
|
156
|
+
# IPv6.
|
|
157
|
+
def get_with_prefix_length(ip_address)
|
|
137
158
|
ip = IPAddr.new(ip_address)
|
|
138
159
|
# We could check the IP has the correct prefix (32 or 128) but I do not
|
|
139
160
|
# for performance reasons.
|
|
@@ -144,10 +165,10 @@ module MaxMind # :nodoc:
|
|
|
144
165
|
"Error looking up #{ip}. You attempted to look up an IPv6 address in an IPv4-only database."
|
|
145
166
|
end
|
|
146
167
|
|
|
147
|
-
pointer = find_address_in_tree(ip, ip_version)
|
|
148
|
-
return nil if pointer == 0
|
|
168
|
+
pointer, depth = find_address_in_tree(ip, ip_version)
|
|
169
|
+
return nil, depth if pointer == 0
|
|
149
170
|
|
|
150
|
-
resolve_data_pointer(pointer)
|
|
171
|
+
[resolve_data_pointer(pointer), depth]
|
|
151
172
|
end
|
|
152
173
|
|
|
153
174
|
private
|
|
@@ -165,19 +186,22 @@ module MaxMind # :nodoc:
|
|
|
165
186
|
node = start_node(bit_count)
|
|
166
187
|
|
|
167
188
|
node_count = @node_count
|
|
168
|
-
bit_count.times do |i|
|
|
169
|
-
break if node >= node_count
|
|
170
189
|
|
|
171
|
-
|
|
172
|
-
|
|
190
|
+
depth = 0
|
|
191
|
+
loop do
|
|
192
|
+
break if depth >= bit_count || node >= node_count
|
|
193
|
+
|
|
194
|
+
c = packed[depth >> 3].ord
|
|
195
|
+
bit = 1 & (c >> 7 - (depth % 8))
|
|
173
196
|
node = read_node(node, bit)
|
|
197
|
+
depth += 1
|
|
174
198
|
end
|
|
175
199
|
|
|
176
|
-
return 0 if node == node_count
|
|
200
|
+
return 0, depth if node == node_count
|
|
177
201
|
|
|
178
|
-
return node if node > node_count
|
|
202
|
+
return node, depth if node > node_count
|
|
179
203
|
|
|
180
|
-
raise InvalidDatabaseError, 'Invalid node in search tree'
|
|
204
|
+
raise InvalidDatabaseError, 'Invalid node in search tree'
|
|
181
205
|
end
|
|
182
206
|
|
|
183
207
|
def start_node(length)
|
|
@@ -205,28 +229,26 @@ module MaxMind # :nodoc:
|
|
|
205
229
|
if @record_size == 24
|
|
206
230
|
offset = index == 0 ? base_offset : base_offset + 3
|
|
207
231
|
buf = @io.read(offset, 3)
|
|
208
|
-
node_bytes = "\x00".
|
|
209
|
-
|
|
210
|
-
# that take the first element to String#unpack1.
|
|
211
|
-
return node_bytes.unpack('N'.freeze)[0]
|
|
232
|
+
node_bytes = "\x00".b << buf
|
|
233
|
+
return node_bytes.unpack1('N')
|
|
212
234
|
end
|
|
213
235
|
|
|
214
236
|
if @record_size == 28
|
|
215
237
|
if index == 0
|
|
216
238
|
buf = @io.read(base_offset, 4)
|
|
217
|
-
n = buf.
|
|
239
|
+
n = buf.unpack1('N')
|
|
218
240
|
last24 = n >> 8
|
|
219
241
|
first4 = (n & 0xf0) << 20
|
|
220
242
|
return first4 | last24
|
|
221
243
|
end
|
|
222
244
|
buf = @io.read(base_offset + 3, 4)
|
|
223
|
-
return buf.
|
|
245
|
+
return buf.unpack1('N') & 0x0fffffff
|
|
224
246
|
end
|
|
225
247
|
|
|
226
248
|
if @record_size == 32
|
|
227
249
|
offset = index == 0 ? base_offset : base_offset + 4
|
|
228
250
|
node_bytes = @io.read(offset, 4)
|
|
229
|
-
return node_bytes.
|
|
251
|
+
return node_bytes.unpack1('N')
|
|
230
252
|
end
|
|
231
253
|
|
|
232
254
|
raise InvalidDatabaseError, "Unsupported record size: #{@record_size}"
|
|
@@ -238,7 +260,7 @@ module MaxMind # :nodoc:
|
|
|
238
260
|
|
|
239
261
|
if offset_in_file >= @size
|
|
240
262
|
raise InvalidDatabaseError,
|
|
241
|
-
'The MaxMind DB file\'s search tree is corrupt'
|
|
263
|
+
'The MaxMind DB file\'s search tree is corrupt'
|
|
242
264
|
end
|
|
243
265
|
|
|
244
266
|
data, = @decoder.decode(offset_in_file)
|
|
@@ -257,7 +279,7 @@ module MaxMind # :nodoc:
|
|
|
257
279
|
end
|
|
258
280
|
|
|
259
281
|
raise InvalidDatabaseError,
|
|
260
|
-
'Metadata section not found. Is this a valid MaxMind DB file?'
|
|
282
|
+
'Metadata section not found. Is this a valid MaxMind DB file?'
|
|
261
283
|
end
|
|
262
284
|
|
|
263
285
|
def at_metadata?(index)
|
data/lib/maxmind/db/decoder.rb
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'maxmind/db/errors'
|
|
2
4
|
|
|
3
5
|
module MaxMind # :nodoc:
|
|
4
6
|
class DB
|
|
5
|
-
# +Decoder+ decodes a {MaxMind DB}[
|
|
7
|
+
# +Decoder+ decodes a {MaxMind DB}[https://maxmind.github.io/MaxMind-DB/]
|
|
6
8
|
# data section.
|
|
7
9
|
#
|
|
8
10
|
# Typically you will interact with this class through a Reader rather than
|
|
@@ -47,44 +49,44 @@ module MaxMind # :nodoc:
|
|
|
47
49
|
def decode_double(size, offset)
|
|
48
50
|
verify_size(8, size)
|
|
49
51
|
buf = @io.read(offset, 8)
|
|
50
|
-
[buf.
|
|
52
|
+
[buf.unpack1('G'), offset + 8]
|
|
51
53
|
end
|
|
52
54
|
|
|
53
55
|
def decode_float(size, offset)
|
|
54
56
|
verify_size(4, size)
|
|
55
57
|
buf = @io.read(offset, 4)
|
|
56
|
-
[buf.
|
|
58
|
+
[buf.unpack1('g'), offset + 4]
|
|
57
59
|
end
|
|
58
60
|
|
|
59
61
|
def verify_size(expected, actual)
|
|
60
62
|
return if expected == actual
|
|
61
63
|
|
|
62
64
|
raise InvalidDatabaseError,
|
|
63
|
-
'The MaxMind DB file\'s data section contains bad data (unknown data type or corrupt data)'
|
|
65
|
+
'The MaxMind DB file\'s data section contains bad data (unknown data type or corrupt data)'
|
|
64
66
|
end
|
|
65
67
|
|
|
66
68
|
def decode_int32(size, offset)
|
|
67
|
-
decode_int('l>'
|
|
69
|
+
decode_int('l>', 4, size, offset)
|
|
68
70
|
end
|
|
69
71
|
|
|
70
72
|
def decode_uint16(size, offset)
|
|
71
|
-
decode_int('n'
|
|
73
|
+
decode_int('n', 2, size, offset)
|
|
72
74
|
end
|
|
73
75
|
|
|
74
76
|
def decode_uint32(size, offset)
|
|
75
|
-
decode_int('N'
|
|
77
|
+
decode_int('N', 4, size, offset)
|
|
76
78
|
end
|
|
77
79
|
|
|
78
80
|
def decode_uint64(size, offset)
|
|
79
|
-
decode_int('Q>'
|
|
81
|
+
decode_int('Q>', 8, size, offset)
|
|
80
82
|
end
|
|
81
83
|
|
|
82
84
|
def decode_int(type_code, type_size, size, offset)
|
|
83
85
|
return 0, offset if size == 0
|
|
84
86
|
|
|
85
87
|
buf = @io.read(offset, size)
|
|
86
|
-
buf = buf.rjust(type_size, "\x00"
|
|
87
|
-
[buf.
|
|
88
|
+
buf = buf.rjust(type_size, "\x00") if size != type_size
|
|
89
|
+
[buf.unpack1(type_code), offset + size]
|
|
88
90
|
end
|
|
89
91
|
|
|
90
92
|
def decode_uint128(size, offset)
|
|
@@ -93,14 +95,14 @@ module MaxMind # :nodoc:
|
|
|
93
95
|
buf = @io.read(offset, size)
|
|
94
96
|
|
|
95
97
|
if size <= 8
|
|
96
|
-
buf = buf.rjust(8, "\x00"
|
|
97
|
-
return buf.
|
|
98
|
+
buf = buf.rjust(8, "\x00")
|
|
99
|
+
return buf.unpack1('Q>'), offset + size
|
|
98
100
|
end
|
|
99
101
|
|
|
100
|
-
a_bytes = buf[0...-8].rjust(8, "\x00"
|
|
102
|
+
a_bytes = buf[0...-8].rjust(8, "\x00")
|
|
101
103
|
b_bytes = buf[-8...buf.length]
|
|
102
|
-
a = a_bytes.
|
|
103
|
-
b = b_bytes.
|
|
104
|
+
a = a_bytes.unpack1('Q>')
|
|
105
|
+
b = b_bytes.unpack1('Q>')
|
|
104
106
|
a <<= 64
|
|
105
107
|
[a | b, offset + size]
|
|
106
108
|
end
|
|
@@ -122,19 +124,19 @@ module MaxMind # :nodoc:
|
|
|
122
124
|
when 0
|
|
123
125
|
new_offset = offset + 1
|
|
124
126
|
buf = (size & 0x7).chr << @io.read(offset, 1)
|
|
125
|
-
pointer = buf.
|
|
127
|
+
pointer = buf.unpack1('n') + @pointer_base
|
|
126
128
|
when 1
|
|
127
129
|
new_offset = offset + 2
|
|
128
|
-
buf = "\x00".
|
|
129
|
-
pointer = buf.
|
|
130
|
+
buf = "\x00".b << (size & 0x7).chr << @io.read(offset, 2)
|
|
131
|
+
pointer = buf.unpack1('N') + 2048 + @pointer_base
|
|
130
132
|
when 2
|
|
131
133
|
new_offset = offset + 3
|
|
132
134
|
buf = (size & 0x7).chr << @io.read(offset, 3)
|
|
133
|
-
pointer = buf.
|
|
135
|
+
pointer = buf.unpack1('N') + 526_336 + @pointer_base
|
|
134
136
|
else
|
|
135
137
|
new_offset = offset + 4
|
|
136
138
|
buf = @io.read(offset, 4)
|
|
137
|
-
pointer = buf.
|
|
139
|
+
pointer = buf.unpack1('N') + @pointer_base
|
|
138
140
|
end
|
|
139
141
|
|
|
140
142
|
return pointer, new_offset if @pointer_test
|
|
@@ -208,9 +210,7 @@ module MaxMind # :nodoc:
|
|
|
208
210
|
def size_from_ctrl_byte(ctrl_byte, offset, type_num)
|
|
209
211
|
size = ctrl_byte & 0x1f
|
|
210
212
|
|
|
211
|
-
return size, offset if type_num == 1
|
|
212
|
-
|
|
213
|
-
return size, offset if size < 29
|
|
213
|
+
return size, offset if type_num == 1 || size < 29
|
|
214
214
|
|
|
215
215
|
if size == 29
|
|
216
216
|
size_bytes = @io.read(offset, 1)
|
|
@@ -220,12 +220,12 @@ module MaxMind # :nodoc:
|
|
|
220
220
|
|
|
221
221
|
if size == 30
|
|
222
222
|
size_bytes = @io.read(offset, 2)
|
|
223
|
-
size = 285 + size_bytes.
|
|
223
|
+
size = 285 + size_bytes.unpack1('n')
|
|
224
224
|
return size, offset + 2
|
|
225
225
|
end
|
|
226
226
|
|
|
227
|
-
size_bytes = "\x00".
|
|
228
|
-
size = 65_821 + size_bytes.
|
|
227
|
+
size_bytes = "\x00".b << @io.read(offset, 3)
|
|
228
|
+
size = 65_821 + size_bytes.unpack1('N')
|
|
229
229
|
[size, offset + 3]
|
|
230
230
|
end
|
|
231
231
|
end
|
data/lib/maxmind/db/errors.rb
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module MaxMind # :nodoc:
|
|
2
4
|
class DB
|
|
3
5
|
# An InvalidDatabaseError means the {MaxMind
|
|
4
|
-
# DB}[
|
|
6
|
+
# DB}[https://maxmind.github.io/MaxMind-DB/] file is corrupt or invalid.
|
|
5
7
|
class InvalidDatabaseError < RuntimeError
|
|
6
8
|
end
|
|
7
9
|
end
|