ipgeolocation 0.1.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.
@@ -0,0 +1,6 @@
1
+ === 0.1.0 / 2009-03-24
2
+
3
+ * First release
4
+
5
+ * Supports 3 remote IP Geolocation services: blogama.org, netgeo, and iphost
6
+
@@ -0,0 +1,6 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/ipgeolocation.rb
6
+ test/test_ipgeolocation.rb
@@ -0,0 +1,62 @@
1
+ = ipgeolocation
2
+
3
+ * http://beforefilter.blogspot.com/
4
+
5
+ == DESCRIPTION:
6
+
7
+ Remote, IP-Based Geolocation for everyone!
8
+
9
+ Seriously, this gem gives you 3 different IP-location services as
10
+ 1-liners. Example:
11
+
12
+ IPGeolocation.locate("12.345.678.90", :blogama)
13
+
14
+ That's all there is to it! And you get a bunch of information, especially
15
+ from blogama's API.
16
+
17
+ == FEATURES/PROBLEMS:
18
+
19
+ * 3 supported IP-Location services
20
+ * no local DB support - this will come in the future once licensing issues
21
+ are determined
22
+
23
+ == SYNOPSIS:
24
+
25
+ IPGeolocation.locate("74.125.45.100", :blogama)
26
+
27
+ gives
28
+
29
+ #<struct IPGeolocation::Location ip="74.125.45.100", country_code="US", country_name="United States", region_code="CA", region_name=nil, city="Mountain View", postal_code="94043", latitude="37.4192", longitude="-122.057">
30
+
31
+ == REQUIREMENTS:
32
+
33
+ * nothing!
34
+
35
+ == INSTALL:
36
+
37
+ * sudo gem install ipgeolocation
38
+
39
+ == LICENSE:
40
+
41
+ (The MIT License)
42
+
43
+ Copyright (c) 2009 Michael J. Edgar
44
+
45
+ Permission is hereby granted, free of charge, to any person obtaining
46
+ a copy of this software and associated documentation files (the
47
+ 'Software'), to deal in the Software without restriction, including
48
+ without limitation the rights to use, copy, modify, merge, publish,
49
+ distribute, sublicense, and/or sell copies of the Software, and to
50
+ permit persons to whom the Software is furnished to do so, subject to
51
+ the following conditions:
52
+
53
+ The above copyright notice and this permission notice shall be
54
+ included in all copies or substantial portions of the Software.
55
+
56
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
57
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
58
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
59
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
60
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
61
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
62
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,76 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/ipgeolocation.rb'
6
+
7
+ Hoe.new('ipgeolocation', IPGeolocation::VERSION) do |p|
8
+ # p.rubyforge_name = 'ipgeolocationx' # if different than lowercase project name
9
+ p.developer('Michael J. Edgar', 'edgar@triqweb.com')
10
+ p.remote_rdoc_dir = ''
11
+
12
+ desc 'Post your blog announcement to blogger.'
13
+ task :post_blogger do
14
+ require 'net/http'
15
+ require 'net/https'
16
+ p.with_config do |config, path|
17
+ break unless config['blogs']
18
+ subject, title, body, urls = p.announcement
19
+ #body += "\n\n#{urls}"
20
+
21
+ config['blogs'].each do |site|
22
+ next unless site['url'] =~ /www\.blogger\.com/
23
+ google_email = site['user']
24
+ google_passwd = site['password']
25
+ source = 'beforefilter.blogspot.com-rubypost'
26
+
27
+ http = Net::HTTP.new('www.google.com', 443)
28
+ http.use_ssl = true
29
+ login_url = '/accounts/ClientLogin'
30
+
31
+ # Setup HTTPS request post data to obtain authentication token.
32
+ data = 'Email=' + google_email +'&Passwd=' + google_passwd + '&source=' + source + '&service=blogger'
33
+ headers = {
34
+ 'Content-Type' => 'application/x-www-form-urlencoded'
35
+ }
36
+
37
+ # Submit HTTPS post request
38
+ resp, data = http.post(login_url, data, headers)
39
+
40
+ unless resp.code.eql? '200'
41
+ puts "Error during authentication, blog at #{site['url']}, ##{site['blog_id']}: #{resp.message}\n"
42
+ else
43
+
44
+ # Parse for the authentication token.
45
+ authToken = data.split("\n").map {|l| l.split("=")}.assoc("Auth")[1]
46
+
47
+ headers = {
48
+ 'Authorization' => 'GoogleLogin auth=' + authToken,
49
+ 'Content-Type' => 'application/atom+xml'
50
+ }
51
+
52
+ data = <<-EOF
53
+ <entry xmlns='http://www.w3.org/2005/Atom'>
54
+ <title type='text'>#{title}</title>
55
+ <content type='xhtml'>
56
+ <div xmlns="http://www.w3.org/1999/xhtml">
57
+ #{body}
58
+ </div>
59
+ </content>
60
+ #{p.blog_categories.inject("") {|acc,cat| acc + "<category scheme=\"http://www.blogger.com/atom/ns#\" term=\"#{cat}\" />\n"}}
61
+ </entry>
62
+ EOF
63
+
64
+ http = Net::HTTP.new('www.blogger.com')
65
+ path = '/feeds/' + site['blog_id'] + '/posts/default'
66
+
67
+ resp, data = http.post(path, data, headers)
68
+ puts "Error while posting, blog at #{site['url']}, ##{site['blog_id']}: #{resp.message}" unless resp.code == 200
69
+ # Expect resp.code == 200 and resp.message == 'OK' for a successful.
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ # vim: syntax=Ruby
@@ -0,0 +1,118 @@
1
+ require 'rexml/document'
2
+ require 'open-uri'
3
+ require 'net/http'
4
+ # = IPGeolocation
5
+ #
6
+ # This library enables IP-Location lookups via remote services.
7
+ # Simply call:
8
+ # IPGeolocation.locate("12.345.678.90", :blogama) # OR
9
+ # IPGeolocation.locate("12.345.678.90", :netgeo) # OR
10
+ # IPGeolocation.locate("12.345.678.90", :hostip)
11
+ #
12
+ # and you will be given a struct with a bunch of nifty information!
13
+ # to its credit, blogama seems to be very, very accurate.
14
+ #
15
+ module IPGeolocation
16
+ VERSION = '0.1.0'
17
+
18
+ ACCEPTABLE_LOCATORS = [:blogama, :netgeo, :hostip]
19
+
20
+ # Fields you can get from the different services
21
+ RESULT_FIELDS = [:ip, :country_code, :country_name, :region_code, :region_name,
22
+ :city, :postal_code, :latitude, :longitude]
23
+
24
+ # Main Location thread. You must choose from one of the available
25
+ # location services. In future versions this will support a local database.
26
+ #
27
+ # Available locators:
28
+ # [:blogama] The Blogama IP database - highly accurate
29
+ # [:netgeo] Netgeo, a legacy IP geolocation service. Doesn't offer zip-codes.
30
+ # [:hostip] Hostip.info - this is a newer location service, but coverage is somewhat spotty.
31
+ #
32
+ # Usage:
33
+ # IPgeolocation.locate("12.345.678.90", :blogama)
34
+ #
35
+ def locate(ip, locator)
36
+ raise ArgumentError.new("Invalid locator: #{locator}") unless ACCEPTABLE_LOCATORS.include?(locator)
37
+ klass = case locator
38
+ when :blogama
39
+ IPGeolocation::BlogamaLocator
40
+ when :netgeo
41
+ IPGeolocation::NetGeoLocator
42
+ when :hostip
43
+ IPGeolocation::HostIPLocator
44
+ end
45
+
46
+ klass.locate(ip)
47
+ end
48
+ module_function :locate
49
+
50
+ # Location interface for hostip.info. Doesn't need to be used directly.
51
+ class HostIPLocator
52
+ HOST_IP_QUERY_URL = "http://api.hostip.info/?"
53
+
54
+ def self.locate ip
55
+ doc = REXML::Document.new(open(IPGeolocation::HostIPLocator::HOST_IP_QUERY_URL+"ip=#{ip}"))
56
+
57
+ result = IPGeolocation::Location.new
58
+ result.ip = ip
59
+ result.country_code = REXML::XPath.first( doc, "//countryAbbrev" ).text.strip
60
+ result.country_name = REXML::XPath.first( doc, "//countryName" ).text.strip
61
+ result.region_code = REXML::XPath.first( doc, "//gml:name" ).text.split(",").last.strip
62
+ result.city = REXML::XPath.first( doc, "//gml:name" ).text.split(",").first.strip
63
+
64
+ coords = REXML::XPath.first( doc, "//gml:coordinates" )
65
+ if coords
66
+ result.latitude = coords.text.split(",").last.strip
67
+ result.longitude = coords.text.split(",").first.strip
68
+ end
69
+ result
70
+ end
71
+ end
72
+
73
+ # Location interface for netgeo.caida.org. Doesn't need to be used directly.
74
+ class NetGeoLocator
75
+
76
+ def self.locate ip
77
+ resp = Net::HTTP.new("netgeo.caida.org").get("/perl/netgeo.cgi?target=#{ip}")
78
+ result = IPGeolocation::Location.new
79
+ fakehash = resp.body.gsub(/<\/?[^>]*>/, "").split("\n").map {|a| a.split ":"}
80
+
81
+ result.ip = fakehash.assoc("TARGET")[1].strip
82
+ result.city = fakehash.assoc("CITY")[1].strip
83
+ result.region_name = fakehash.assoc("STATE")[1].strip
84
+ result.country_code = fakehash.assoc("COUNTRY")[1].strip
85
+ result.latitude = fakehash.assoc("LAT")[1].strip
86
+ result.longitude = fakehash.assoc("LONG")[1].strip
87
+ result
88
+ end
89
+ end
90
+
91
+ # Location interface for blogama.org. Doesn't need to be used directly.
92
+ class BlogamaLocator
93
+ BLOGAMA_QUERY_URL = "http://blogama.org/ip_query.php?"
94
+
95
+ def self.locate ip
96
+ doc = REXML::Document.new(open(IPGeolocation::BlogamaLocator::BLOGAMA_QUERY_URL+"ip=#{ip}&output=xml"))
97
+
98
+ root = doc.root
99
+ puts root
100
+ result = IPGeolocation::Location.new
101
+ result.ip = root.elements["Ip"].text
102
+ result.country_code = root.elements["CountryCode"].text
103
+ result.country_name = root.elements["CountryName"].text
104
+ result.region_code = root.elements["RegionCode"].text
105
+ result.region_name = root.elements["RegionName"].text
106
+ result.city = root.elements["City"].text
107
+ result.postal_code = root.elements["ZipPostalCode"].text
108
+ result.latitude = root.elements["Latitude"].text
109
+ result.longitude = root.elements["Longitude"].text
110
+
111
+ result
112
+ end
113
+ end
114
+
115
+ # Struct for holding all relevant info from GeoLocation services
116
+ class Location < Struct.new(*IPGeolocation::RESULT_FIELDS)
117
+ end
118
+ end
@@ -0,0 +1,8 @@
1
+ require "test/unit"
2
+ require "ipgeolocation"
3
+
4
+ class TestIpgeolocation < Test::Unit::TestCase
5
+ def test_sanity
6
+ flunk "write tests or I will kneecap you"
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ipgeolocation
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Michael J. Edgar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-25 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.11.0
24
+ version:
25
+ description: "Remote, IP-Based Geolocation for everyone! Seriously, this gem gives you 3 different IP-location services as 1-liners. Example: IPGeolocation.locate(\"12.345.678.90\", :blogama) That's all there is to it! And you get a bunch of information, especially from blogama's API."
26
+ email:
27
+ - edgar@triqweb.com
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files:
33
+ - History.txt
34
+ - Manifest.txt
35
+ - README.txt
36
+ files:
37
+ - History.txt
38
+ - Manifest.txt
39
+ - README.txt
40
+ - Rakefile
41
+ - lib/ipgeolocation.rb
42
+ - test/test_ipgeolocation.rb
43
+ has_rdoc: true
44
+ homepage: http://beforefilter.blogspot.com/
45
+ post_install_message:
46
+ rdoc_options:
47
+ - --main
48
+ - README.txt
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ version:
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ requirements: []
64
+
65
+ rubyforge_project: ipgeolocation
66
+ rubygems_version: 1.3.1
67
+ signing_key:
68
+ specification_version: 2
69
+ summary: Remote, IP-Based Geolocation for everyone! Seriously, this gem gives you 3 different IP-location services as 1-liners
70
+ test_files:
71
+ - test/test_ipgeolocation.rb