pure_mmdb 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|