geoip 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,8 +1,12 @@
1
- == 0.5.0 2007-10-24
1
+ == 0.8.0 2008-08-29
2
2
 
3
- * 1 major enhancement:
4
- * Initial release
3
+ * Added Mutex protection around file I/O for thread safety
5
4
 
6
5
  == 0.7.0 2008-05-03
7
6
 
8
7
  * Added Hez Ronningen's patch for using the ISP lookup data file
8
+
9
+ == 0.5.0 2007-10-24
10
+
11
+ * 1 major enhancement:
12
+ * Initial release
data/README.txt CHANGED
@@ -1,5 +1,25 @@
1
+ = GeoIP
2
+
3
+ http://geoip.rubyforge.org/
4
+
5
+ == DESCRIPTION:
6
+
1
7
  GeoIP searches a GeoIP database for a given host or IP address, and
2
- returns information about the country where the IP address is allocated.
8
+ returns information about the country where the IP address is allocated,
9
+ and the city, ISP and other information, if you have that database version.
10
+
11
+ == FEATURES/PROBLEMS:
12
+
13
+ This release applies a Mutex around file I/O operations, which should
14
+ prevent GeoIP blowing up under multi-threaded usage.
15
+
16
+ == SYNOPSIS:
17
+
18
+ require 'geoip'
19
+ GeoIP.new('GeoIP.dat').country("www.netscape.sk")
20
+ => ["www.netscape.sk", "217.67.16.35", 196, "SK", "SVK", "Slovakia", "EU"]
21
+
22
+ == REQUIREMENTS:
3
23
 
4
24
  You need at least the free GeoIP.dat, for which the last known download
5
25
  location is <http://www.maxmind.com/download/geoip/database/GeoIP.dat.gz>,
@@ -10,3 +30,33 @@ of this database are available for purchase which contain more detailed
10
30
  information, but this information is not returned by this implementation.
11
31
  See www.maxmind.com for more information.
12
32
 
33
+ == INSTALL:
34
+
35
+ sudo gem install geoip
36
+
37
+ == LICENSE:
38
+
39
+ (The MIT License)
40
+
41
+ Copyright (c) 2008 FIX
42
+
43
+ Permission is hereby granted, free of charge, to any person obtaining
44
+ a copy of this software and associated documentation files (the
45
+ 'Software'), to deal in the Software without restriction, including
46
+ without limitation the rights to use, copy, modify, merge, publish,
47
+ distribute, sublicense, and/or sell copies of the Software, and to
48
+ permit persons to whom the Software is furnished to do so, subject to
49
+ the following conditions:
50
+
51
+ The above copyright notice and this permission notice shall be
52
+ included in all copies or substantial portions of the Software.
53
+
54
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
55
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
56
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
57
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
58
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
59
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
60
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
61
+
62
+ ==
@@ -41,6 +41,7 @@ $:.unshift File.dirname(__FILE__)
41
41
  # See www.maxmind.com for more information.
42
42
  #
43
43
  #=end
44
+ require 'thread' # Needed for Mutex
44
45
 
45
46
  require 'socket'
46
47
 
@@ -421,11 +422,13 @@ class GeoIP
421
422
 
422
423
  public
423
424
  attr_reader :databaseType
425
+
424
426
  # Open the GeoIP database and determine the file format version
425
427
  #
426
428
  # +filename+ is a String holding the path to the GeoIP.dat file
427
429
  # +options+ is an integer holding caching flags (unimplemented)
428
430
  def initialize(filename, flags = 0)
431
+ @mutex = Mutex.new
429
432
  @flags = flags
430
433
  @databaseType = GEOIP_COUNTRY_EDITION
431
434
  @record_length = STANDARD_RECORD_LENGTH
@@ -525,8 +528,11 @@ class GeoIP
525
528
  private
526
529
 
527
530
  def read_city(pos, hostname = '', ip = '')
528
- @file.seek(pos + (2*@record_length-1) * @databaseSegments[0])
529
- return nil if((record = @file.read(FULL_RECORD_LENGTH)).nil?)
531
+ record = ""
532
+ @mutex.synchronize {
533
+ @file.seek(pos + (2*@record_length-1) * @databaseSegments[0])
534
+ return nil unless record = @file.read(FULL_RECORD_LENGTH)
535
+ }
530
536
 
531
537
  # The country code is the first byte:
532
538
  code = record[0]
@@ -632,22 +638,25 @@ class GeoIP
632
638
  # Return the ISP name
633
639
  #
634
640
  def isp(hostname)
635
- ip = hostname
636
- if ip.kind_of?(String) && ip !~ /^[0-9.]*$/
637
- # Lookup IP address, we were given a name
638
- ip = IPSocket.getaddress(hostname)
639
- end
640
-
641
- # Convert numeric IP address to an integer
642
- ipnum = iptonum(ip)
643
- if @databaseType != GEOIP_ISP_EDITION then
644
- throw "Invalid GeoIP database type, can't look up Organization/ISP by IP"
645
- end
646
- pos = seek_record(ipnum);
647
- @file.seek(pos + (2*@record_length-1) * @databaseSegments[0])
648
- record = @file.read(MAX_ORG_RECORD_LENGTH)
649
- record = record.sub(/\000.*/, '')
650
- record
641
+ ip = hostname
642
+ if ip.kind_of?(String) && ip !~ /^[0-9.]*$/
643
+ # Lookup IP address, we were given a name
644
+ ip = IPSocket.getaddress(hostname)
645
+ end
646
+
647
+ # Convert numeric IP address to an integer
648
+ ipnum = iptonum(ip)
649
+ if @databaseType != GEOIP_ISP_EDITION
650
+ throw "Invalid GeoIP database type, can't look up Organization/ISP by IP"
651
+ end
652
+ pos = seek_record(ipnum);
653
+ record = ""
654
+ @mutex.synchronize {
655
+ @file.seek(pos + (2*@record_length-1) * @databaseSegments[0])
656
+ record = @file.read(MAX_ORG_RECORD_LENGTH)
657
+ }
658
+ record = record.sub(/\000.*/, '')
659
+ record
651
660
  end
652
661
 
653
662
  # Search a ISP GeoIP database for the specified host, returning the organization
@@ -689,8 +698,10 @@ class GeoIP
689
698
  offset = 0
690
699
  mask = 0x80000000
691
700
  31.downto(0) { |depth|
692
- @file.seek(@record_length * 2 * offset);
693
- buf = @file.read(@record_length * 2);
701
+ buf = @mutex.synchronize {
702
+ @file.seek(@record_length * 2 * offset);
703
+ @file.read(@record_length * 2);
704
+ }
694
705
  buf.slice!(0...@record_length) if ((ipnum & mask) != 0)
695
706
  offset = le_to_ui(buf[0...@record_length].unpack("C*"))
696
707
  return offset if (offset >= @databaseSegments[0])
@@ -1,7 +1,7 @@
1
1
  module Geoip #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 7
4
+ MINOR = 8
5
5
  TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
@@ -33,7 +33,7 @@
33
33
  <h1>geoip</h1>
34
34
  <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/geoip"; return false'>
35
35
  <p>Get Version</p>
36
- <a href="http://rubyforge.org/projects/geoip" class="numbers">0.7.0</a>
36
+ <a href="http://rubyforge.org/projects/geoip" class="numbers">0.8.0</a>
37
37
  </div>
38
38
  <h2>&#x2192; &#8216;Geographic info for an IP address&#8217;</h2>
39
39
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geoip
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Clifford Heath
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-05-03 00:00:00 +10:00
12
+ date: 2008-08-29 00:00:00 +10:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -73,7 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
73
  requirements: []
74
74
 
75
75
  rubyforge_project: geoip
76
- rubygems_version: 1.1.0
76
+ rubygems_version: 1.2.0
77
77
  signing_key:
78
78
  specification_version: 2
79
79
  summary: description of gem