geoipdb 0.5.8 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 960fb22c30747c4351d08c9bcc2ec6b42ec91315
4
- data.tar.gz: a6b72d92b471418e70c3a15f3c4626c1e4de6eca
3
+ metadata.gz: 4a9d74eeb52c1411ef3b7615bdab98fa6ed21550
4
+ data.tar.gz: e496789447d83354ca3bb9305361cb836aef0671
5
5
  SHA512:
6
- metadata.gz: 44f537dd1fb6558f3804fb0cabf8b174b6f3ecee197ed7dbb0c33f30626cf1b7ad7896908547cfdf4f97bf600e64c049f0aa489e5c8c7e8083aa271e8e3e7e22
7
- data.tar.gz: c032a9926161171273711583fb5056f99a984f6dc7ea55b244fc15b6f4492b3b062ed3485470f42c7f266d299cfd29abf382c8c437cd042d8e5a9271d6b54aeb
6
+ metadata.gz: 4e85f35fbdd49016fa40b71be6a31ea14ed80dcdc75baaadc39124b43afa7f8f5df196851f8be3d1ac18fa3e37d473704bbca6440bb2a204c77f41a0744f368b
7
+ data.tar.gz: 842b770d73b5e0f054688f3bd45448c04a925a60c3b18ae5aa6324af1a67f352a84070e474f4b95c6e6755eb7a87ff9b738f1fb0300eadd13ef556e0d5f20480
data/.gitignore CHANGED
@@ -5,14 +5,6 @@
5
5
  Gemfile.lock
6
6
  coverage
7
7
  doc
8
- ext/Makefile
9
- ext/geoipdb/Makefile
10
- ext/geoipdb/geoipdb.bundle
11
- ext/geoipdb/geoipdb.o
12
- ext/geoipdb/ipdb.o
13
- ext/geoipdb/test
14
- ext/geoipdb/test.o
15
- lib/geoipdb.jar
16
8
  pkg
17
9
  rdoc
18
10
  tags
@@ -0,0 +1 @@
1
+ jruby
data/Gemfile CHANGED
@@ -1,9 +1,7 @@
1
- source "https://rubygems.org"
1
+ source "http://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'liquid-ext'
6
-
7
5
  group :development, :test do
8
6
  gem 'liquid-development'
9
7
  end
@@ -0,0 +1,10 @@
1
+ all: jar
2
+
3
+ clean:
4
+ rm -rf lib/geoipdb.jar
5
+
6
+ compile: clean
7
+ javac `find src/ -name '*.java'`
8
+
9
+ jar: compile
10
+ jar cvf lib/geoipdb.jar -C src/ .
data/README.md CHANGED
@@ -1,9 +1,6 @@
1
- # geoipdb: fast (in memory!) geo location db.
1
+ # GeoIPDB
2
2
 
3
- Fast GeoIpDb implementation for Ruby using C/Java-Extensions.
4
-
5
- * Returns a GeoLocation and additional information for a given IP.
6
- * Reads Data from CSV-Files and uses internal binary caching.
3
+ Fast GeoIPDB implementation for JRuby.
7
4
 
8
5
  [![Gem Version](https://badge.fury.io/rb/geoipdb.png)](http://badge.fury.io/rb/geoipdb)
9
6
  [![Build Status](https://secure.travis-ci.org/liquidm/geoipdb.png)](http://travis-ci.org/liquidm/geoipdb)
data/Rakefile CHANGED
@@ -1,16 +1,3 @@
1
1
  require "bundler/setup"
2
2
  require "bundler/gem_tasks"
3
3
  require "liquid/tasks"
4
-
5
- case RUBY_PLATFORM
6
- when 'java'
7
- require 'rake/javaextensiontask'
8
- Rake::JavaExtensionTask.new('geoipdb')
9
- else
10
- require 'rake/extensiontask'
11
- Rake::ExtensionTask.new('geoipdb')
12
- end
13
-
14
- task :default => [:spec]
15
- task :build => :compile
16
- task :spec => :compile
@@ -2,25 +2,18 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "geoipdb"
5
- spec.version = "0.5.8"
5
+ spec.version = "1.0.0"
6
6
  spec.authors = ["LiquidM, Inc."]
7
7
  spec.email = ["opensource@liquidm.com"]
8
- spec.description = "Fast GeoIpDb implementation for Ruby"
9
- spec.summary = "Fast GeoIpDb implementation for Ruby"
8
+ spec.description = "Fast IPDB implementation for JRuby"
9
+ spec.summary = "Fast IPDB implementation for JRuby"
10
10
  spec.homepage = "http://github.com/liquidm/geoipdb"
11
11
  spec.licenses = ["MIT"]
12
12
 
13
13
  spec.files = `git ls-files`.split($/)
14
14
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
15
15
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
16
- spec.require_paths = ["lib", "ext"]
16
+ spec.require_paths = ["lib"]
17
17
 
18
- if RUBY_PLATFORM =~ /java/
19
- spec.platform = "java"
20
- spec.files << "lib/geoipdb.jar"
21
- else
22
- spec.extensions = ["ext/geoipdb/extconf.rb"]
23
- end
24
-
25
- spec.add_development_dependency "rake-compiler"
18
+ spec.add_dependency "liquid-ext"
26
19
  end
Binary file
@@ -1,7 +1,226 @@
1
- require 'ip_information'
1
+ require 'liquid/boot'
2
+
3
+ require 'fileutils'
4
+ require 'open-uri'
5
+ require 'singleton'
6
+ require 'uri'
7
+ require 'zlib'
8
+
9
+ java_import 'java.lang.NumberFormatException'
10
+ java_import 'java.net.InetAddress'
11
+
12
+ require File.expand_path('../geoipdb.jar', __FILE__)
13
+
14
+ class IPDB
15
+ include Singleton
16
+
17
+ attr_accessor :base_url
18
+
19
+ DATA_FILES = [
20
+ 'cities.csv',
21
+ 'ip_ranges.csv',
22
+ ]
23
+
24
+ class IPDBError < Exception
25
+ end
26
+
27
+ def self.init(base_url)
28
+ instance.update!(base_url)
29
+ end
30
+
31
+ def self.lookup(ip)
32
+ instance.lookup(ip)
33
+ end
34
+
35
+ def initialize
36
+ @version = Gem.loaded_specs['geoipdb'].version.to_s
37
+ @cache_path = File.expand_path("~/.cache/geoipdb/v#{@version}")
38
+ # by default load sample data
39
+ sample_path = File.expand_path('../../sample_data', __FILE__)
40
+ files = DATA_FILES.map { |file_name| File.join(sample_path, file_name) }
41
+ self.load(*files)
42
+ end
43
+
44
+ def load(*files)
45
+ @db = Java::IPDB.new(*files)
46
+ end
47
+
48
+ def update!(base_url)
49
+ return nil if @initialized
50
+ @start = Time.now.to_f
51
+ @base_url = base_url
52
+ @initialized = true
53
+
54
+ $log.info("ipdb:load", cache_path: @cache_path)
55
+ FileUtils.mkdir_p(@cache_path)
56
+
57
+ @updating = false
58
+ if !uptodate?
59
+ @updating = true
60
+ $log.info("ipdb:init", update: true)
61
+ download_update
62
+ end
63
+
64
+ load_data_files
65
+ end
66
+
67
+ def load_data_files
68
+ files = DATA_FILES.map { |file_name| File.join(@cache_path, file_name) }
69
+ self.load(*files)
70
+ self_test
71
+ make_backup if @updating
72
+ $log.info("ipdb:init", rt: Time.now.to_f - @start)
73
+ rescue IPDBError => e
74
+ $log.exception(e)
75
+ $log.info("ipdb:init", revert: true)
76
+ restore_backup
77
+ load_data_files
78
+ self_test
79
+ end
80
+
81
+ def lookup(ip)
82
+ return nil unless @db
83
+ ip = InetAddress.get_by_name(ip).address if ip.is_a?(String)
84
+ range = @db.find_range_for_ip(ip)
85
+ return nil unless range
86
+ city = @db.find_city_for_ip_range(range)
87
+ return nil unless city
88
+ isp = range.isp_name
89
+ info = IpInformation.new
90
+ info.country_iso_code = city.country_iso2
91
+ info.city_name = city.name
92
+ info.city_code = city.city_code
93
+ info.lng = city.lng
94
+ info.lat = city.lat
95
+ info.is_mobile = range.is_mobile
96
+ info.isp_name = isp && isp.to_sym
97
+ info
98
+ rescue EncodingError, NumberFormatException
99
+ # TODO: do we really want to silence these exceptions?
100
+ return nil
101
+ end
102
+
103
+ private
104
+
105
+ def uptodate?
106
+ days14 = 24*60*60*14 # 14days
107
+ now = Time.now.to_f
108
+
109
+ DATA_FILES.each do |file_name|
110
+ path = File.join(@cache_path, file_name)
111
+ if !File.exist?(path)
112
+ $log.info("ipdb:check", result: false, file: file_name, reason: "#{path} does not exist")
113
+ return false
114
+ elsif File.stat(path).ctime.to_f + days14 < now
115
+ $log.info("ipdb:check", result: false, file: file_name, reason: "#{path} is too old - needs update!")
116
+ return false
117
+ else
118
+ $log.info("ipdb:check", result: true, file: file_name)
119
+ end
120
+ end
121
+ return true
122
+ end
123
+
124
+ def download_update
125
+ DATA_FILES.each do |file_name|
126
+ download(file_name)
127
+ unzip(file_name)
128
+ end
129
+ end
130
+
131
+ def download(file_name)
132
+ $log.info("ipdb:download", file: file_name)
133
+ file_name = "#{file_name}.gz"
134
+ source = URI.parse("#{@base_url}/#{file_name}")
135
+ dest = "#{@cache_path}/#{file_name}"
136
+ File.write(dest, source.read)
137
+ end
138
+
139
+ def unzip(file_name)
140
+ $log.info("ipdb:unzip", file: file_name)
141
+ source = File.join(@cache_path, "#{file_name}.gz")
142
+ dest = File.join(@cache_path, file_name)
143
+ Zlib::GzipReader.open(source) do |gz|
144
+ File.write(dest, gz.read)
145
+ end
146
+ end
147
+
148
+ def make_backup
149
+ DATA_FILES.each do |file_name|
150
+ path = File.join(@cache_path, file_name)
151
+ backup_path = File.join(@cache_path, "#{file_name}.backup")
152
+ next unless File.exists?(path)
153
+ $log.info("ipdb:backup", path: path, backup_path: backup_path)
154
+ FileUtils.cp(path, backup_path)
155
+ end
156
+ end
157
+
158
+ def restore_backup
159
+ DATA_FILES.each do |file_name|
160
+ path = File.join(@cache_path, file_name)
161
+ backup_path = File.join(@cache_path, "#{file_name}.backup")
162
+ if File.exists?(backup_path)
163
+ $log.info("ipdb:restore", backup_path: backup_path, path: path)
164
+ FileUtils.cp(backup_path, path)
165
+ else
166
+ $log.error("ipdb:restore", reason: "#{backup_path} does not exist")
167
+ return false
168
+ end
169
+ end
170
+ return true
171
+ end
172
+
173
+ def self_test
174
+ {
175
+ '10.0.0.1' => '--',
176
+ '127.0.0.1' => '--',
177
+ '192.168.1.1' => '--',
178
+ '93.219.159.76' => 'de',
179
+ '91.44.76.101' => 'de',
180
+ '82.113.100.1' => 'de',
181
+ '84.1.10.4' => 'hu',
182
+ '83.23.11.5' => 'pl',
183
+ '52.13.100.1' => 'us',
184
+ }.each do |ip, country|
185
+ result = lookup(ip)
186
+ next if country == result.country_iso_code
187
+ raise IPDBError.new("IPDB selftest FAILED! IP lookup failed: #{ip} should be #{country} but was #{result.country_iso_code}.")
188
+ end
189
+ return true
190
+ end
191
+
192
+ end
193
+
194
+ class IpInformation
195
+
196
+ ATTRIBS = [
197
+ :country_iso_code,
198
+ :city_code,
199
+ :city_name,
200
+ :lat,
201
+ :lng,
202
+ :is_mobile,
203
+ :isp_name,
204
+ ]
205
+
206
+ ATTRIBS.each do |attrib|
207
+ attr_accessor attrib
208
+ end
209
+
210
+ def initialize(attribs = {})
211
+ attribs.each do |key, value|
212
+ send("#{key}=", value)
213
+ end
214
+ end
215
+
216
+ def mobile?
217
+ @is_mobile
218
+ end
219
+
220
+ def to_h
221
+ Hash[ATTRIBS.map do |attrib|
222
+ [attrib, send(attrib)]
223
+ end]
224
+ end
2
225
 
3
- if defined?(JRUBY_VERSION)
4
- require 'jgeoipdb'
5
- else
6
- require 'cgeoipdb'
7
226
  end
@@ -1,9 +1,9 @@
1
- start_ip,end_ip,connection_type,city_code,isp_name
1
+ start_ip,end_ip,conn-speed,city-code,isp-name
2
2
  0.0.0.0,0.0.0.255,mobile,0,?
3
3
  0.0.1.0,0.255.255.255,mobile,1,asdf,
4
4
  1.0.0.0,1.0.0.255,xdsl,2,vodafone
5
5
  1.0.1.0,1.1.0.255,wireless,3,?
6
- 1.1.1.0,1.1.1.255,mobile,4,1vodafone2vodafone3vodafone4vodafone5vodafone1vodafone2vodafone3vodafone4vodafone5vodafone1vodafone2vodafone3vodafone4vodafone5vodafone1vodafone2vodafone3vodafone4vodafone5vodafone
6
+ 1.1.1.0,1.1.1.255,mobile,4,o2
7
7
  1.1.2.0,1.2.2.255,mobile,5,?
8
8
  1.2.3.0,1.2.3.255,mobile,5,?
9
9
  1.2.4.0,1.3.255.255,mobile,2,?
@@ -1,38 +1,9 @@
1
- require File.expand_path(File.dirname(__FILE__)+'/spec_helper')
1
+ require 'geoipdb'
2
2
 
3
-
4
- describe GeoIpDb do
5
-
6
- CACHE_FILE = 'sample_data/ipdb.cache'
7
-
8
- def init_db
9
- @db = GeoIpDb.init './sample_data/cities.csv', './sample_data/ip_ranges.csv', CACHE_FILE
10
- end
11
-
12
- it "should not throw an exception fault if data is corrupt" do
13
- @db = GeoIpDb.init './sample_data/cities_corrupt.csv', './sample_data/ip_ranges_corrupt.csv', CACHE_FILE
14
- end
15
-
16
- it "should not init a db object if data files are missing" do
17
- GeoIpDb.init( './sample_data/bla.csv', './sample_data/blubb.csv', CACHE_FILE ).should be_nil
18
- end
19
-
20
- it "should init correctly with sample data" do
21
- init_db
22
- @db.should_not be_nil
23
- end
24
-
25
- unless defined? JRUBY_VERSION
26
- it "initializes cache_file correctly with sample data" do
27
- init_db
28
- File.exist?(CACHE_FILE).should be_true
29
- end
30
- end
3
+ describe IPDB do
31
4
 
32
5
  it "sould find the sample cities correcty" do
33
- init_db
34
- #afg,no region,kabul,-1,3,34.5167,69.1833
35
- info = @db.information_for_ip "1.1.0.254"
6
+ info = IPDB.lookup "1.1.0.254"
36
7
  info.city_code.should == 3
37
8
  info.city_name.should == 'kabul'
38
9
  info.country_iso_code.should == 'af'
@@ -42,20 +13,14 @@ describe GeoIpDb do
42
13
  end
43
14
 
44
15
  it 'should return correct is_mobile information' do
45
- init_db
46
- @db.information_for_ip("1.0.0.1").should_not be_mobile
47
- @db.information_for_ip("1.1.1.1").should be_mobile
16
+ IPDB.lookup("1.0.0.1").should_not be_mobile
17
+ IPDB.lookup("1.1.1.1").should be_mobile
48
18
  end
49
19
 
50
20
  it 'should return correct isp_name in ip_information' do
51
- init_db
52
- @db.information_for_ip("1.0.0.1").isp_name.should == :vodafone
53
- @db.information_for_ip("1.1.1.1").isp_name.should == "1vodafone2vodafone3vodafone4vodafone5vodafone1vodafone2vodafone3vodafone4vodafone5vodafone1vodafone2vodafone3vodafone4vodafone5vodafone1vodafone2vodafone3vodafone4vodafone5vodafone"[0..99].to_sym
54
- @db.information_for_ip("1.2.1.1").isp_name.should == :"?"
55
- end
56
-
57
- after :each do
58
- File.unlink CACHE_FILE if File.exist? CACHE_FILE
21
+ IPDB.lookup("1.0.0.1").isp_name.should == :vodafone
22
+ IPDB.lookup("1.1.1.1").isp_name.should == :o2
23
+ IPDB.lookup("1.2.1.1").isp_name.should == :"?"
59
24
  end
60
25
 
61
26
  end
@@ -1,12 +1,15 @@
1
- require 'rubygems'
2
- require 'rspec'
1
+ ROOT = File.expand_path('../..', __FILE__)
3
2
 
4
- require 'simplecov'
5
- SimpleCov.start
3
+ require 'bundler/setup'
4
+ require 'liquid/boot'
6
5
 
7
- $:.unshift(File.dirname(__FILE__) + '/../lib')
8
- $:.unshift(File.dirname(__FILE__) + '/../ext')
9
- require 'geoipdb'
6
+ require 'rspec'
10
7
 
8
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
11
9
  RSpec.configure do |config|
10
+ # Run specs in random order to surface order dependencies. If you find an
11
+ # order dependency and want to debug it, you can fix the order by providing
12
+ # the seed, which is printed after each run.
13
+ # --seed 1234
14
+ config.order = 'random'
12
15
  end