geoip_multi 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/geoip_multi.rb +144 -0
  2. metadata +64 -0
@@ -0,0 +1,144 @@
1
+ # Extension to Native Ruby reader for the GeoIP database
2
+ # Added support for netmask() and range_by_ip()
3
+ # Created new method to retrieve all available information based on
4
+ # the various GeoIP database files that are available
5
+ #
6
+ # = COPYRIGHT
7
+ #
8
+ # This version Copyright (C) 2013 Ryan Harris
9
+ # Derived from the C version, Copyright (C) 2003 MaxMind LLC
10
+ #
11
+ # This library is free software; you can redistribute it and/or
12
+ # modify it under the terms of the GNU Lesser General Public
13
+ # License as published by the Free Software Foundation; either
14
+ # version 2.1 of the License, or (at your option) any later version.
15
+ #
16
+ # This library is distributed in the hope that it will be useful,
17
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19
+ # Lesser General Public License for more details.
20
+ #
21
+ # You should have received a copy of the GNU Lesser General Public
22
+ # License along with this library; if not, write to the Free Software
23
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24
+ # = SYNOPSIS
25
+ #
26
+ # require 'geoip_multi'
27
+ # GeoIPMulti.new('/usr/share/GeoIP/').lookup('24.24.24.24')
28
+ #
29
+ # = DESCRIPTION
30
+ #
31
+ # GeoIP searches a GeoIP database for a given host or IP address, and
32
+ # returns information about the country where the IP address is allocated.
33
+ #
34
+ # = PREREQUISITES
35
+ #
36
+ # You need at least the free GeoIP.dat, for which the last known download
37
+ # location is <http://www.maxmind.com/download/geoip/database/GeoIP.dat.gz>
38
+ # This API requires the file to be decompressed for searching. Other versions
39
+ # of this database are available for purchase which contain more detailed
40
+ # information, but this information is not returned by this implementation.
41
+ # See www.maxmind.com for more information.
42
+
43
+ gem 'geoip', '>=1.3.3'
44
+ require 'geoip'
45
+
46
+ class GeoIP
47
+ @last_netmask=0
48
+
49
+ def netmask (ip)
50
+ seek_netmask(iptonum(ip))
51
+ @last_netmask
52
+ end
53
+
54
+ def filename
55
+ @file.path
56
+ end
57
+
58
+ def range_by_ip(ip)
59
+ ipnum = iptonum(ip)
60
+ record=seek_netmask(ipnum)
61
+ mask = 0xffffffff << 32 - @last_netmask
62
+ left_seek_num = ipnum & mask
63
+ right_seek_num = left_seek_num + ( 0xffffffff & ~mask )
64
+ while (left_seek_num !=0 and record == seek_netmask(left_seek_num - 1))
65
+ leftmask = 0xffffffff << 32 - @last_netmask
66
+ left_seek_num = (left_seek_num - 1) & leftmask
67
+ end
68
+ while (right_seek_num != 0xffffffff and record == seek_netmask(right_seek_num + 1))
69
+ rightmask = 0xffffffff << 32 - @last_netmask
70
+ right_seek_num = ( right_seek_num + 1 ) & rightmask
71
+ right_seek_num += (0xffffffff & ~rightmask)
72
+ end
73
+ [numtoip(left_seek_num), numtoip(right_seek_num)]
74
+ end
75
+
76
+ private
77
+
78
+ def numtoip(ipnum) #:nodoc:
79
+ IPAddr.new(ipnum, Socket::AF_INET).to_s
80
+ end
81
+
82
+ def seek_netmask(ipnum) #:nodoc:
83
+ # minor modification of original seek_record() method to include updating @last_netmask
84
+ offset = 0
85
+ 31.downto(0) do |depth|
86
+ off = (@record_length * 2 * offset)
87
+ buf = atomic_read(@record_length * 2, off)
88
+ buf.slice!(0...@record_length) if ((ipnum & (1 << depth)) != 0)
89
+ offset = le_to_ui(buf[0...@record_length].unpack("C*"))
90
+ if (offset >= @database_segments[0])
91
+ @last_netmask = 32 - depth
92
+ return offset
93
+ end
94
+ end
95
+ end
96
+
97
+ end
98
+
99
+ class GeoIPMulti < GeoIP
100
+
101
+ def initialize (*filenames)
102
+ @geoip_databases=[]
103
+ filenames=Dir.glob(File.join(File.expand_path($0)[/(.*\/)/],'*.dat')) if filenames.length == 0
104
+ add_database(filenames)
105
+ end
106
+
107
+ def add_database (*filenames)
108
+ filenames.flatten!
109
+ filenames.each do |filename|
110
+ if File.directory?(filename)
111
+ Dir.glob(File.join(filename,'*.dat')) {|filename| @geoip_databases << GeoIP.new(filename)}
112
+ else
113
+ GeoIP.new(filename)
114
+ @geoip_databases << GeoIP.new(filename)
115
+ end
116
+ end
117
+ end
118
+
119
+ def lookup(ip)
120
+ results ={}
121
+ @geoip_databases.each do |current_database|
122
+ case current_database.database_type
123
+ #IPv4 addresses expected, IPv6 not currently supported, maybe in the future...
124
+ when GEOIP_COUNTRY_EDITION
125
+ results.merge!(current_database.country(ip).to_hash)
126
+ when GEOIP_CITY_EDITION_REV1
127
+ results.merge!(current_database.city(ip).to_hash)
128
+ results.merge!(:netmask=>current_database.netmask(ip))
129
+ iprange = current_database.range_by_ip(ip)
130
+ results.merge!(:first_ip => iprange[0],:last_ip => iprange[1])
131
+ when GEOIP_ISP_EDITION
132
+ results.merge!(:isp=>current_database.isp(ip))
133
+ when GEOIP_ORG_EDITION
134
+ results.merge!(current_database.filename[/([^\/]+)$/][/(?:GeoIP)?([^.]+)/,1].downcase.to_sym => current_database.isp(ip))
135
+ when GEOIP_ASNUM_EDITION
136
+ results.merge!(current_database.asn(ip).to_hash)
137
+ else
138
+ puts "Unknown or Unsupported GeoIP database type:"
139
+ puts "filename:#{current_database.filename} => database_type:#{current_database.database_type}"
140
+ end
141
+ end
142
+ results
143
+ end
144
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: geoip_multi
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ryan Harris
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-12-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: geoip
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.3.3
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.3.3
30
+ description: ==Extends native ruby geoip gem. Adds support for netmask() and range_by_ip()
31
+ methods to the GeoIP class and creates a new class GeoIPMulti that performs lookups
32
+ on multiple GeoIP databases with a single lookup() method
33
+ email: rubygems.rharris@neverbox.com
34
+ executables: []
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - lib/geoip_multi.rb
39
+ homepage: http://github.com/rlh6f/GeoIPMulti
40
+ licenses:
41
+ - GPL
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubyforge_project:
60
+ rubygems_version: 1.8.23
61
+ signing_key:
62
+ specification_version: 3
63
+ summary: Extension of geoip
64
+ test_files: []