pure_mmdb 0.2.0 → 0.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.
- checksums.yaml +5 -5
- data/.gitignore +0 -2
- data/.travis.yml +9 -5
- data/Gemfile +4 -2
- data/Gemfile.lock +21 -21
- data/Rakefile +5 -19
- data/bin/console +4 -3
- data/lib/mmdb/configuration.rb +2 -0
- data/lib/mmdb/db.rb +25 -14
- data/lib/mmdb/decoder.rb +8 -5
- data/lib/mmdb/query.rb +2 -0
- data/lib/mmdb/version.rb +3 -1
- data/lib/mmdb.rb +10 -15
- data/mmdb.gemspec +20 -19
- metadata +9 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f8802f1401a6393ae12434a4e641406ccd3c88eef1d79c9cfb9ed4be05635e32
|
4
|
+
data.tar.gz: 4e490273a556bcb6e5a82bbaddb73449742e72a8f98b7d1558708f4fe3bcf154
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 786886fc0f4eb99b148ee5501ad775f2c36cf0ae14368a058a016eb19cb6ac41698f15cc741e53e2db6cec3c74f0f2080b374cb6fbe466f359abccb315c3e564
|
7
|
+
data.tar.gz: 00bf41b8e96779fc34c78426e53f89950ede79cc247592b4c13a9c23c8b6500108ce2d4db672bd41097244fde671483d205f2a689ba4d0de958582464d824a23
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -4,10 +4,11 @@ env:
|
|
4
4
|
sudo: false
|
5
5
|
language: ruby
|
6
6
|
rvm:
|
7
|
-
- 2.
|
8
|
-
- 2.
|
9
|
-
- 2.
|
10
|
-
|
7
|
+
- 2.4
|
8
|
+
- 2.5
|
9
|
+
- 2.6
|
10
|
+
- 2.7
|
11
|
+
before_install: gem install bundler
|
11
12
|
before_script:
|
12
13
|
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
13
14
|
- chmod +x ./cc-test-reporter
|
@@ -16,4 +17,7 @@ script:
|
|
16
17
|
- bundle exec rake
|
17
18
|
after_script:
|
18
19
|
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
19
|
-
|
20
|
+
notifications:
|
21
|
+
email:
|
22
|
+
on_success: never # default: change
|
23
|
+
on_failure: always # default: always
|
data/Gemfile
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
4
6
|
|
5
7
|
# Specify your gem's dependencies in mmdb.gemspec
|
6
8
|
gemspec
|
data/Gemfile.lock
CHANGED
@@ -6,40 +6,40 @@ PATH
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
byebug (
|
9
|
+
byebug (11.1.1)
|
10
10
|
coderay (1.1.2)
|
11
11
|
diff-lcs (1.3)
|
12
|
-
method_source (0.9.
|
13
|
-
pry (0.
|
12
|
+
method_source (0.9.2)
|
13
|
+
pry (0.12.2)
|
14
14
|
coderay (~> 1.1.0)
|
15
15
|
method_source (~> 0.9.0)
|
16
|
-
pry-byebug (3.
|
17
|
-
byebug (~>
|
16
|
+
pry-byebug (3.8.0)
|
17
|
+
byebug (~> 11.0)
|
18
18
|
pry (~> 0.10)
|
19
|
-
rake (
|
20
|
-
rspec (3.
|
21
|
-
rspec-core (~> 3.
|
22
|
-
rspec-expectations (~> 3.
|
23
|
-
rspec-mocks (~> 3.
|
24
|
-
rspec-core (3.
|
25
|
-
rspec-support (~> 3.
|
26
|
-
rspec-expectations (3.
|
19
|
+
rake (13.0.1)
|
20
|
+
rspec (3.9.0)
|
21
|
+
rspec-core (~> 3.9.0)
|
22
|
+
rspec-expectations (~> 3.9.0)
|
23
|
+
rspec-mocks (~> 3.9.0)
|
24
|
+
rspec-core (3.9.1)
|
25
|
+
rspec-support (~> 3.9.1)
|
26
|
+
rspec-expectations (3.9.1)
|
27
27
|
diff-lcs (>= 1.2.0, < 2.0)
|
28
|
-
rspec-support (~> 3.
|
29
|
-
rspec-mocks (3.
|
28
|
+
rspec-support (~> 3.9.0)
|
29
|
+
rspec-mocks (3.9.1)
|
30
30
|
diff-lcs (>= 1.2.0, < 2.0)
|
31
|
-
rspec-support (~> 3.
|
32
|
-
rspec-support (3.
|
31
|
+
rspec-support (~> 3.9.0)
|
32
|
+
rspec-support (3.9.2)
|
33
33
|
|
34
34
|
PLATFORMS
|
35
35
|
ruby
|
36
36
|
|
37
37
|
DEPENDENCIES
|
38
|
-
bundler (
|
39
|
-
pry-byebug (
|
38
|
+
bundler (>= 1.16)
|
39
|
+
pry-byebug (>= 3.0)
|
40
40
|
pure_mmdb!
|
41
|
-
rake (
|
41
|
+
rake (>= 10.0)
|
42
42
|
rspec (~> 3.0)
|
43
43
|
|
44
44
|
BUNDLED WITH
|
45
|
-
1.
|
45
|
+
2.1.4
|
data/Rakefile
CHANGED
@@ -1,22 +1,8 @@
|
|
1
|
-
|
2
|
-
require "rspec/core/rake_task"
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
desc "Downloads maxmind free DBs if required"
|
7
|
-
task :ensure_maxmind_files do
|
8
|
-
unless File.exist?('spec/data/GeoLite2-City.mmdb')
|
9
|
-
sh 'curl http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz -o spec/data/GeoLite2-City.mmdb.gz'
|
10
|
-
sh 'gunzip spec/data/GeoLite2-City.mmdb.gz'
|
11
|
-
end
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rspec/core/rake_task'
|
12
5
|
|
13
|
-
|
14
|
-
sh 'curl http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz -o spec/data/GeoLite2-Country.mmdb.gz'
|
15
|
-
sh 'gunzip spec/data/GeoLite2-Country.mmdb.gz'
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
desc "Downloads maxmind free DBs if required and runs all specs"
|
20
|
-
task ensure_maxmind_files_and_spec: [:ensure_maxmind_files, :spec]
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
21
7
|
|
22
|
-
task default: :
|
8
|
+
task default: :spec
|
data/bin/console
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require
|
4
|
-
require
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'mmdb'
|
5
6
|
|
6
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
8
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +11,5 @@ require "mmdb"
|
|
10
11
|
# require "pry"
|
11
12
|
# Pry.start
|
12
13
|
|
13
|
-
require
|
14
|
+
require 'irb'
|
14
15
|
IRB.start(__FILE__)
|
data/lib/mmdb/configuration.rb
CHANGED
data/lib/mmdb/db.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Mmdb
|
2
4
|
class DB
|
3
|
-
class InvalidFileFormat < RuntimeError
|
5
|
+
class InvalidFileFormat < RuntimeError; end
|
4
6
|
|
5
7
|
def initialize(file_path)
|
6
8
|
@file_path = file_path
|
@@ -8,18 +10,7 @@ module Mmdb
|
|
8
10
|
|
9
11
|
def query(ip_addr)
|
10
12
|
validate_database!
|
11
|
-
|
12
|
-
(decoder.start_index...128).each do |i|
|
13
|
-
flag = (ip_addr >> (127 - i)) & 1
|
14
|
-
next_node = decoder.read(node: node, flag: flag)
|
15
|
-
raise InvalidFileFormat if next_node.zero?
|
16
|
-
if next_node < decoder.node_count
|
17
|
-
node = next_node
|
18
|
-
else
|
19
|
-
return decode_node(next_node).value
|
20
|
-
end
|
21
|
-
end
|
22
|
-
raise InvalidFileFormat
|
13
|
+
find_node!(ip_addr)
|
23
14
|
end
|
24
15
|
|
25
16
|
private
|
@@ -28,6 +19,26 @@ module Mmdb
|
|
28
19
|
|
29
20
|
attr_reader :file_path
|
30
21
|
|
22
|
+
def find_node!(ip_addr)
|
23
|
+
(decoder.start_index...128).inject(0) do |node, i|
|
24
|
+
next_node = read_next_node!(node, build_flag(ip_addr, i))
|
25
|
+
return decode_node(next_node).value if next_node >= decoder.node_count
|
26
|
+
|
27
|
+
next_node
|
28
|
+
end
|
29
|
+
raise InvalidFileFormat
|
30
|
+
end
|
31
|
+
|
32
|
+
def build_flag(ip_addr, index)
|
33
|
+
(ip_addr >> (127 - index)) & 1
|
34
|
+
end
|
35
|
+
|
36
|
+
def read_next_node!(node, flag)
|
37
|
+
decoder.read(node: node, flag: flag).tap do |next_node|
|
38
|
+
raise InvalidFileFormat if next_node.zero?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
31
42
|
def validate_database!
|
32
43
|
raise Mmdb::DatabaseNotFound unless File.exist?(file_path)
|
33
44
|
end
|
@@ -39,7 +50,7 @@ module Mmdb
|
|
39
50
|
end
|
40
51
|
|
41
52
|
def decoder
|
42
|
-
@
|
53
|
+
@decoder ||= Decoder.new(File.binread(file_path))
|
43
54
|
end
|
44
55
|
end
|
45
56
|
end
|
data/lib/mmdb/decoder.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Mmdb
|
2
4
|
class Decoder
|
3
5
|
def initialize(data)
|
@@ -9,6 +11,7 @@ module Mmdb
|
|
9
11
|
begin
|
10
12
|
index = data.rindex(METADATA_BEGIN)
|
11
13
|
raise InvalidFileFormat if index.nil?
|
14
|
+
|
12
15
|
decode(position: index + METADATA_BEGIN.size, base: 0).value
|
13
16
|
end
|
14
17
|
end
|
@@ -18,15 +21,15 @@ module Mmdb
|
|
18
21
|
end
|
19
22
|
|
20
23
|
def ip_version
|
21
|
-
metadata[
|
24
|
+
metadata['ip_version']
|
22
25
|
end
|
23
26
|
|
24
27
|
def node_count
|
25
|
-
metadata[
|
28
|
+
metadata['node_count']
|
26
29
|
end
|
27
30
|
|
28
31
|
def node_byte_size
|
29
|
-
@node_byte_size ||= metadata[
|
32
|
+
@node_byte_size ||= metadata['record_size'] * 2 / 8
|
30
33
|
end
|
31
34
|
|
32
35
|
def search_tree_size
|
@@ -122,8 +125,8 @@ module Mmdb
|
|
122
125
|
attr_reader :data
|
123
126
|
|
124
127
|
METADATA_BEGIN = ([0xAB, 0xCD, 0xEF].pack('C*') + 'MaxMind.com').encode('ascii-8bit', 'ascii-8bit')
|
125
|
-
SIZE_BASE_VALUES = [0, 29, 285,
|
126
|
-
POINTER_BASE_VALUES = [0, 0, 2048,
|
128
|
+
SIZE_BASE_VALUES = [0, 29, 285, 65_821].freeze
|
129
|
+
POINTER_BASE_VALUES = [0, 0, 2048, 526_336].freeze
|
127
130
|
Node = Struct.new(:position, :value)
|
128
131
|
TYPES = [
|
129
132
|
EXTENDED_TYPE = 0,
|
data/lib/mmdb/query.rb
CHANGED
data/lib/mmdb/version.rb
CHANGED
data/lib/mmdb.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'mmdb/configuration'
|
4
|
+
require 'mmdb/db'
|
5
|
+
require 'mmdb/decoder'
|
6
|
+
require 'mmdb/query'
|
7
|
+
require 'mmdb/version'
|
6
8
|
|
7
9
|
module Mmdb
|
8
|
-
class DatabaseNotFound < RuntimeError
|
10
|
+
class DatabaseNotFound < RuntimeError; end
|
9
11
|
|
10
12
|
class << self
|
11
13
|
attr_reader :config
|
@@ -26,19 +28,12 @@ module Mmdb
|
|
26
28
|
|
27
29
|
private
|
28
30
|
|
29
|
-
attr_reader :databases
|
30
|
-
|
31
31
|
def db_for_key(file_key)
|
32
|
-
databases
|
33
|
-
raise DatabaseNotFound if db.nil?
|
34
|
-
end
|
32
|
+
databases.fetch(file_key) { raise DatabaseNotFound }
|
35
33
|
end
|
36
34
|
|
37
35
|
def databases
|
38
|
-
@databases ||=
|
39
|
-
config.files.map do |key, file_path|
|
40
|
-
[key, DB.new(file_path)]
|
41
|
-
end.to_h
|
36
|
+
@databases ||= Hash[config.files.map { |k, f| [k, DB.new(f)] }]
|
42
37
|
end
|
43
38
|
end
|
44
39
|
end
|
data/mmdb.gemspec
CHANGED
@@ -1,37 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
|
-
lib = File.expand_path(
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
5
|
+
require 'mmdb/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
8
|
+
spec.name = 'pure_mmdb'
|
8
9
|
spec.version = Mmdb::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
10
|
+
spec.authors = ['Trevor John']
|
11
|
+
spec.email = ['trevor@john.tj']
|
11
12
|
|
12
|
-
spec.summary =
|
13
|
-
spec.description =
|
14
|
-
spec.homepage =
|
15
|
-
spec.license =
|
13
|
+
spec.summary = 'This is a ruby implementation of the MaxMindDB file format'
|
14
|
+
spec.description = 'The purpose of this gem is to provide fast IP lookups for the MaxMindDB file format without parsing the data stored.'
|
15
|
+
spec.homepage = 'https://github.com/trevorrjohn/mmdb'
|
16
|
+
spec.license = 'MIT'
|
16
17
|
|
17
18
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
18
19
|
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
19
20
|
if spec.respond_to?(:metadata)
|
20
|
-
spec.metadata[
|
21
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
21
22
|
else
|
22
|
-
raise
|
23
|
-
|
23
|
+
raise 'RubyGems 2.0 or newer is required to protect against ' \
|
24
|
+
'public gem pushes.'
|
24
25
|
end
|
25
26
|
|
26
|
-
spec.files
|
27
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
27
28
|
f.match(%r{^(test|spec|features)/})
|
28
29
|
end
|
29
|
-
spec.bindir =
|
30
|
+
spec.bindir = 'exe'
|
30
31
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
31
|
-
spec.require_paths = [
|
32
|
+
spec.require_paths = ['lib']
|
32
33
|
|
33
|
-
spec.add_development_dependency
|
34
|
-
spec.add_development_dependency
|
35
|
-
spec.add_development_dependency
|
36
|
-
spec.add_development_dependency
|
34
|
+
spec.add_development_dependency 'bundler', '>= 1.16'
|
35
|
+
spec.add_development_dependency 'pry-byebug', '>= 3.0'
|
36
|
+
spec.add_development_dependency 'rake', '>= 10.0'
|
37
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
37
38
|
end
|
metadata
CHANGED
@@ -1,55 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pure_mmdb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Trevor John
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-03-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.16'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.16'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: pry-byebug
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '3.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '3.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '10.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '10.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
@@ -112,8 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
112
|
- !ruby/object:Gem::Version
|
113
113
|
version: '0'
|
114
114
|
requirements: []
|
115
|
-
|
116
|
-
rubygems_version: 2.6.13
|
115
|
+
rubygems_version: 3.1.2
|
117
116
|
signing_key:
|
118
117
|
specification_version: 4
|
119
118
|
summary: This is a ruby implementation of the MaxMindDB file format
|