geoipdb 0.5.8 → 1.0.0

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