ultra-fast-mod 0.0.1
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 +7 -0
- data/geocoder-1.8.6/CHANGELOG.md +669 -0
- data/geocoder-1.8.6/LICENSE +20 -0
- data/geocoder-1.8.6/README.md +827 -0
- data/geocoder-1.8.6/bin/console +13 -0
- data/geocoder-1.8.6/bin/geocode +5 -0
- data/geocoder-1.8.6/examples/app_defined_lookup_services.rb +22 -0
- data/geocoder-1.8.6/examples/cache_bypass.rb +48 -0
- data/geocoder-1.8.6/examples/reverse_geocode_job.rb +40 -0
- data/geocoder-1.8.6/lib/easting_northing.rb +171 -0
- data/geocoder-1.8.6/lib/generators/geocoder/config/config_generator.rb +14 -0
- data/geocoder-1.8.6/lib/generators/geocoder/config/templates/initializer.rb +27 -0
- data/geocoder-1.8.6/lib/generators/geocoder/maxmind/geolite_city_generator.rb +30 -0
- data/geocoder-1.8.6/lib/generators/geocoder/maxmind/geolite_country_generator.rb +30 -0
- data/geocoder-1.8.6/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb +30 -0
- data/geocoder-1.8.6/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb +17 -0
- data/geocoder-1.8.6/lib/generators/geocoder/migration_version.rb +15 -0
- data/geocoder-1.8.6/lib/geocoder/cache.rb +77 -0
- data/geocoder-1.8.6/lib/geocoder/cache_stores/base.rb +40 -0
- data/geocoder-1.8.6/lib/geocoder/cache_stores/generic.rb +35 -0
- data/geocoder-1.8.6/lib/geocoder/cache_stores/redis.rb +34 -0
- data/geocoder-1.8.6/lib/geocoder/calculations.rb +420 -0
- data/geocoder-1.8.6/lib/geocoder/cli.rb +121 -0
- data/geocoder-1.8.6/lib/geocoder/configuration.rb +151 -0
- data/geocoder-1.8.6/lib/geocoder/configuration_hash.rb +11 -0
- data/geocoder-1.8.6/lib/geocoder/esri_token.rb +38 -0
- data/geocoder-1.8.6/lib/geocoder/exceptions.rb +40 -0
- data/geocoder-1.8.6/lib/geocoder/ip_address.rb +36 -0
- data/geocoder-1.8.6/lib/geocoder/kernel_logger.rb +25 -0
- data/geocoder-1.8.6/lib/geocoder/logger.rb +47 -0
- data/geocoder-1.8.6/lib/geocoder/lookup.rb +155 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/abstract_api.rb +46 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/amap.rb +63 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/amazon_location_service.rb +58 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/azure.rb +56 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/baidu.rb +63 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/baidu_ip.rb +30 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/ban_data_gouv_fr.rb +143 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/base.rb +351 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/bing.rb +82 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/db_ip_com.rb +52 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/esri.rb +114 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/freegeoip.rb +62 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/geoapify.rb +78 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/geocoder_ca.rb +53 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/geocodio.rb +42 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/geoip2.rb +49 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/geoportail_lu.rb +65 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/google.rb +100 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/google_places_details.rb +64 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/google_places_search.rb +75 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/google_premier.rb +61 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/here.rb +73 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/ip2location.rb +71 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/ip2location_io.rb +62 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/ip2location_lite.rb +40 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/ipapi_com.rb +82 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/ipbase.rb +49 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/ipdata_co.rb +62 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/ipgeolocation.rb +51 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/ipinfo_io.rb +44 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/ipinfo_io_lite.rb +42 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/ipqualityscore.rb +50 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/ipregistry.rb +68 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/ipstack.rb +63 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/latlon.rb +58 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/location_iq.rb +54 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/mapbox.rb +60 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/mapquest.rb +58 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/maxmind.rb +90 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/maxmind_geoip2.rb +70 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/maxmind_local.rb +71 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/melissa_street.rb +41 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/nominatim.rb +64 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/opencagedata.rb +65 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/osmnames.rb +57 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/pc_miler.rb +87 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/pdok_nl.rb +43 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/pelias.rb +63 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/photon.rb +89 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/pickpoint.rb +41 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/pointpin.rb +69 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/postcode_anywhere_uk.rb +50 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/postcodes_io.rb +31 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/smarty_streets.rb +68 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/telize.rb +75 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/tencent.rb +59 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/test.rb +49 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/twogis.rb +58 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/uk_ordnance_survey_names.rb +59 -0
- data/geocoder-1.8.6/lib/geocoder/lookups/yandex.rb +61 -0
- data/geocoder-1.8.6/lib/geocoder/models/active_record.rb +51 -0
- data/geocoder-1.8.6/lib/geocoder/models/base.rb +39 -0
- data/geocoder-1.8.6/lib/geocoder/models/mongo_base.rb +62 -0
- data/geocoder-1.8.6/lib/geocoder/models/mongo_mapper.rb +26 -0
- data/geocoder-1.8.6/lib/geocoder/models/mongoid.rb +32 -0
- data/geocoder-1.8.6/lib/geocoder/query.rb +125 -0
- data/geocoder-1.8.6/lib/geocoder/railtie.rb +26 -0
- data/geocoder-1.8.6/lib/geocoder/request.rb +114 -0
- data/geocoder-1.8.6/lib/geocoder/results/abstract_api.rb +146 -0
- data/geocoder-1.8.6/lib/geocoder/results/amap.rb +87 -0
- data/geocoder-1.8.6/lib/geocoder/results/amazon_location_service.rb +62 -0
- data/geocoder-1.8.6/lib/geocoder/results/azure.rb +65 -0
- data/geocoder-1.8.6/lib/geocoder/results/baidu.rb +75 -0
- data/geocoder-1.8.6/lib/geocoder/results/baidu_ip.rb +62 -0
- data/geocoder-1.8.6/lib/geocoder/results/ban_data_gouv_fr.rb +282 -0
- data/geocoder-1.8.6/lib/geocoder/results/base.rb +79 -0
- data/geocoder-1.8.6/lib/geocoder/results/bing.rb +52 -0
- data/geocoder-1.8.6/lib/geocoder/results/db_ip_com.rb +58 -0
- data/geocoder-1.8.6/lib/geocoder/results/esri.rb +78 -0
- data/geocoder-1.8.6/lib/geocoder/results/freegeoip.rb +40 -0
- data/geocoder-1.8.6/lib/geocoder/results/geoapify.rb +179 -0
- data/geocoder-1.8.6/lib/geocoder/results/geocoder_ca.rb +60 -0
- data/geocoder-1.8.6/lib/geocoder/results/geocodio.rb +78 -0
- data/geocoder-1.8.6/lib/geocoder/results/geoip2.rb +76 -0
- data/geocoder-1.8.6/lib/geocoder/results/geoportail_lu.rb +71 -0
- data/geocoder-1.8.6/lib/geocoder/results/google.rb +150 -0
- data/geocoder-1.8.6/lib/geocoder/results/google_places_details.rb +39 -0
- data/geocoder-1.8.6/lib/geocoder/results/google_places_search.rb +52 -0
- data/geocoder-1.8.6/lib/geocoder/results/google_premier.rb +6 -0
- data/geocoder-1.8.6/lib/geocoder/results/here.rb +77 -0
- data/geocoder-1.8.6/lib/geocoder/results/ip2location.rb +22 -0
- data/geocoder-1.8.6/lib/geocoder/results/ip2location_io.rb +21 -0
- data/geocoder-1.8.6/lib/geocoder/results/ip2location_lite.rb +47 -0
- data/geocoder-1.8.6/lib/geocoder/results/ipapi_com.rb +45 -0
- data/geocoder-1.8.6/lib/geocoder/results/ipbase.rb +40 -0
- data/geocoder-1.8.6/lib/geocoder/results/ipdata_co.rb +40 -0
- data/geocoder-1.8.6/lib/geocoder/results/ipgeolocation.rb +59 -0
- data/geocoder-1.8.6/lib/geocoder/results/ipinfo_io.rb +48 -0
- data/geocoder-1.8.6/lib/geocoder/results/ipinfo_io_lite.rb +16 -0
- data/geocoder-1.8.6/lib/geocoder/results/ipqualityscore.rb +54 -0
- data/geocoder-1.8.6/lib/geocoder/results/ipregistry.rb +304 -0
- data/geocoder-1.8.6/lib/geocoder/results/ipstack.rb +60 -0
- data/geocoder-1.8.6/lib/geocoder/results/latlon.rb +71 -0
- data/geocoder-1.8.6/lib/geocoder/results/location_iq.rb +6 -0
- data/geocoder-1.8.6/lib/geocoder/results/mapbox.rb +80 -0
- data/geocoder-1.8.6/lib/geocoder/results/mapquest.rb +48 -0
- data/geocoder-1.8.6/lib/geocoder/results/maxmind.rb +130 -0
- data/geocoder-1.8.6/lib/geocoder/results/maxmind_geoip2.rb +9 -0
- data/geocoder-1.8.6/lib/geocoder/results/maxmind_local.rb +44 -0
- data/geocoder-1.8.6/lib/geocoder/results/melissa_street.rb +46 -0
- data/geocoder-1.8.6/lib/geocoder/results/nationaal_georegister_nl.rb +62 -0
- data/geocoder-1.8.6/lib/geocoder/results/nominatim.rb +121 -0
- data/geocoder-1.8.6/lib/geocoder/results/opencagedata.rb +100 -0
- data/geocoder-1.8.6/lib/geocoder/results/osmnames.rb +56 -0
- data/geocoder-1.8.6/lib/geocoder/results/pc_miler.rb +98 -0
- data/geocoder-1.8.6/lib/geocoder/results/pdok_nl.rb +62 -0
- data/geocoder-1.8.6/lib/geocoder/results/pelias.rb +58 -0
- data/geocoder-1.8.6/lib/geocoder/results/photon.rb +119 -0
- data/geocoder-1.8.6/lib/geocoder/results/pickpoint.rb +6 -0
- data/geocoder-1.8.6/lib/geocoder/results/pointpin.rb +40 -0
- data/geocoder-1.8.6/lib/geocoder/results/postcode_anywhere_uk.rb +42 -0
- data/geocoder-1.8.6/lib/geocoder/results/postcodes_io.rb +40 -0
- data/geocoder-1.8.6/lib/geocoder/results/smarty_streets.rb +142 -0
- data/geocoder-1.8.6/lib/geocoder/results/telize.rb +40 -0
- data/geocoder-1.8.6/lib/geocoder/results/tencent.rb +72 -0
- data/geocoder-1.8.6/lib/geocoder/results/test.rb +33 -0
- data/geocoder-1.8.6/lib/geocoder/results/twogis.rb +76 -0
- data/geocoder-1.8.6/lib/geocoder/results/uk_ordnance_survey_names.rb +59 -0
- data/geocoder-1.8.6/lib/geocoder/results/yandex.rb +292 -0
- data/geocoder-1.8.6/lib/geocoder/sql.rb +110 -0
- data/geocoder-1.8.6/lib/geocoder/stores/active_record.rb +329 -0
- data/geocoder-1.8.6/lib/geocoder/stores/base.rb +115 -0
- data/geocoder-1.8.6/lib/geocoder/stores/mongo_base.rb +58 -0
- data/geocoder-1.8.6/lib/geocoder/stores/mongo_mapper.rb +13 -0
- data/geocoder-1.8.6/lib/geocoder/stores/mongoid.rb +13 -0
- data/geocoder-1.8.6/lib/geocoder/util.rb +29 -0
- data/geocoder-1.8.6/lib/geocoder/version.rb +3 -0
- data/geocoder-1.8.6/lib/geocoder.rb +48 -0
- data/geocoder-1.8.6/lib/maxmind_database.rb +109 -0
- data/geocoder-1.8.6/lib/tasks/geocoder.rake +54 -0
- data/geocoder-1.8.6/lib/tasks/maxmind.rake +73 -0
- data/ultra-fast-mod.gemspec +12 -0
- metadata +214 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
module Geocoder
|
|
2
|
+
class Query
|
|
3
|
+
attr_accessor :text, :options
|
|
4
|
+
|
|
5
|
+
def initialize(text, options = {})
|
|
6
|
+
self.text = text
|
|
7
|
+
self.options = options
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def execute
|
|
11
|
+
lookup.search(text, options)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def to_s
|
|
15
|
+
text
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def sanitized_text
|
|
19
|
+
if coordinates?
|
|
20
|
+
if text.is_a?(Array)
|
|
21
|
+
text.join(',')
|
|
22
|
+
else
|
|
23
|
+
text.split(/\s*,\s*/).join(',')
|
|
24
|
+
end
|
|
25
|
+
else
|
|
26
|
+
text.to_s.strip
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
##
|
|
31
|
+
# Get a Lookup object (which communicates with the remote geocoding API)
|
|
32
|
+
# appropriate to the Query text.
|
|
33
|
+
#
|
|
34
|
+
def lookup
|
|
35
|
+
if !options[:street_address] and (options[:ip_address] or ip_address?)
|
|
36
|
+
name = options[:ip_lookup] || Configuration.ip_lookup || Geocoder::Lookup.ip_services.first
|
|
37
|
+
else
|
|
38
|
+
name = options[:lookup] || Configuration.lookup || Geocoder::Lookup.street_services.first
|
|
39
|
+
end
|
|
40
|
+
Lookup.get(name)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def url
|
|
44
|
+
lookup.query_url(self)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# Is the Query blank? (ie, should we not bother searching?)
|
|
49
|
+
# A query is considered blank if its text is nil or empty string AND
|
|
50
|
+
# no URL parameters are specified.
|
|
51
|
+
#
|
|
52
|
+
def blank?
|
|
53
|
+
!params_given? and (
|
|
54
|
+
(text.is_a?(Array) and text.compact.size < 2) or
|
|
55
|
+
text.to_s.match(/\A\s*\z/)
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
##
|
|
60
|
+
# Does the Query text look like an IP address?
|
|
61
|
+
#
|
|
62
|
+
# Does not check for actual validity, just the appearance of four
|
|
63
|
+
# dot-delimited numbers.
|
|
64
|
+
#
|
|
65
|
+
def ip_address?
|
|
66
|
+
IpAddress.new(text).valid? rescue false
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
##
|
|
70
|
+
# Is the Query text a loopback or private IP address?
|
|
71
|
+
#
|
|
72
|
+
def internal_ip_address?
|
|
73
|
+
ip_address? && IpAddress.new(text).internal?
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
##
|
|
77
|
+
# Is the Query text a loopback IP address?
|
|
78
|
+
#
|
|
79
|
+
def loopback_ip_address?
|
|
80
|
+
ip_address? && IpAddress.new(text).loopback?
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
##
|
|
84
|
+
# Is the Query text a private IP address?
|
|
85
|
+
#
|
|
86
|
+
def private_ip_address?
|
|
87
|
+
ip_address? && IpAddress.new(text).private?
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
##
|
|
91
|
+
# Does the given string look like latitude/longitude coordinates?
|
|
92
|
+
#
|
|
93
|
+
def coordinates?
|
|
94
|
+
text.is_a?(Array) or (
|
|
95
|
+
text.is_a?(String) and
|
|
96
|
+
!!text.to_s.match(/\A-?[0-9\.]+, *-?[0-9\.]+\z/)
|
|
97
|
+
)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
##
|
|
101
|
+
# Return the latitude/longitude coordinates specified in the query,
|
|
102
|
+
# or nil if none.
|
|
103
|
+
#
|
|
104
|
+
def coordinates
|
|
105
|
+
sanitized_text.split(',') if coordinates?
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
##
|
|
109
|
+
# Should reverse geocoding be performed for this query?
|
|
110
|
+
#
|
|
111
|
+
def reverse_geocode?
|
|
112
|
+
coordinates?
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def language
|
|
116
|
+
options[:language]
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
private # ----------------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
def params_given?
|
|
122
|
+
!!(options[:params].is_a?(Hash) and options[:params].keys.size > 0)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'geocoder/models/active_record'
|
|
2
|
+
|
|
3
|
+
module Geocoder
|
|
4
|
+
if defined? Rails::Railtie
|
|
5
|
+
require 'rails'
|
|
6
|
+
class Railtie < Rails::Railtie
|
|
7
|
+
initializer 'geocoder.insert_into_active_record', before: :load_config_initializers do
|
|
8
|
+
ActiveSupport.on_load :active_record do
|
|
9
|
+
Geocoder::Railtie.insert
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
rake_tasks do
|
|
13
|
+
load "tasks/geocoder.rake"
|
|
14
|
+
load "tasks/maxmind.rake"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class Railtie
|
|
20
|
+
def self.insert
|
|
21
|
+
if defined?(::ActiveRecord)
|
|
22
|
+
::ActiveRecord::Base.extend(Model::ActiveRecord)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
require 'ipaddr'
|
|
2
|
+
|
|
3
|
+
module Geocoder
|
|
4
|
+
module Request
|
|
5
|
+
|
|
6
|
+
# The location() method is vulnerable to trivial IP spoofing.
|
|
7
|
+
# Don't use it in authorization/authentication code, or any
|
|
8
|
+
# other security-sensitive application. Use safe_location
|
|
9
|
+
# instead.
|
|
10
|
+
def location
|
|
11
|
+
@location ||= Geocoder.search(geocoder_spoofable_ip, ip_address: true).first
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# This safe_location() protects you from trivial IP spoofing.
|
|
15
|
+
# For requests that go through a proxy that you haven't
|
|
16
|
+
# whitelisted as trusted in your Rack config, you will get the
|
|
17
|
+
# location for the IP of the last untrusted proxy in the chain,
|
|
18
|
+
# not the original client IP. You WILL NOT get the location
|
|
19
|
+
# corresponding to the original client IP for any request sent
|
|
20
|
+
# through a non-whitelisted proxy.
|
|
21
|
+
def safe_location
|
|
22
|
+
@safe_location ||= Geocoder.search(ip, ip_address: true).first
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# There's a whole zoo of nonstandard headers added by various
|
|
26
|
+
# proxy softwares to indicate original client IP.
|
|
27
|
+
# ANY of these can be trivially spoofed!
|
|
28
|
+
# (except REMOTE_ADDR, which should by set by your server,
|
|
29
|
+
# and is included at the end as a fallback.
|
|
30
|
+
# Order does matter: we're following the convention established in
|
|
31
|
+
# ActionDispatch::RemoteIp::GetIp::calculate_ip()
|
|
32
|
+
# https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/remote_ip.rb
|
|
33
|
+
# where the forwarded_for headers, possibly containing lists,
|
|
34
|
+
# are arbitrarily preferred over headers expected to contain a
|
|
35
|
+
# single address.
|
|
36
|
+
GEOCODER_CANDIDATE_HEADERS = ['HTTP_X_FORWARDED_FOR',
|
|
37
|
+
'HTTP_X_FORWARDED',
|
|
38
|
+
'HTTP_FORWARDED_FOR',
|
|
39
|
+
'HTTP_FORWARDED',
|
|
40
|
+
'HTTP_X_CLIENT_IP',
|
|
41
|
+
'HTTP_CLIENT_IP',
|
|
42
|
+
'HTTP_X_REAL_IP',
|
|
43
|
+
'HTTP_X_CLUSTER_CLIENT_IP',
|
|
44
|
+
'REMOTE_ADDR']
|
|
45
|
+
|
|
46
|
+
def geocoder_spoofable_ip
|
|
47
|
+
|
|
48
|
+
# We could use a more sophisticated IP-guessing algorithm here,
|
|
49
|
+
# in which we'd try to resolve the use of different headers by
|
|
50
|
+
# different proxies. The idea is that by comparing IPs repeated
|
|
51
|
+
# in different headers, you can sometimes decide which header
|
|
52
|
+
# was used by a proxy further along in the chain, and thus
|
|
53
|
+
# prefer the headers used earlier. However, the gains might not
|
|
54
|
+
# be worth the performance tradeoff, since this method is likely
|
|
55
|
+
# to be called on every request in a lot of applications.
|
|
56
|
+
GEOCODER_CANDIDATE_HEADERS.each do |header|
|
|
57
|
+
if @env.has_key? header
|
|
58
|
+
addrs = geocoder_split_ip_addresses(@env[header])
|
|
59
|
+
addrs = geocoder_remove_port_from_addresses(addrs)
|
|
60
|
+
addrs = geocoder_reject_non_ipv4_addresses(addrs)
|
|
61
|
+
addrs = geocoder_reject_trusted_ip_addresses(addrs)
|
|
62
|
+
return addrs.first if addrs.any?
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
@env['REMOTE_ADDR']
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def geocoder_split_ip_addresses(ip_addresses)
|
|
72
|
+
ip_addresses ? ip_addresses.strip.split(/[,\s]+/) : []
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# use Rack's trusted_proxy?() method to filter out IPs that have
|
|
76
|
+
# been configured as trusted; includes private ranges by
|
|
77
|
+
# default. (we don't want every lookup to return the location
|
|
78
|
+
# of our own proxy/load balancer)
|
|
79
|
+
def geocoder_reject_trusted_ip_addresses(ip_addresses)
|
|
80
|
+
ip_addresses.reject { |ip| trusted_proxy?(ip) }
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def geocoder_remove_port_from_addresses(ip_addresses)
|
|
84
|
+
ip_addresses.map do |ip|
|
|
85
|
+
# IPv4
|
|
86
|
+
if ip.count('.') > 0
|
|
87
|
+
ip.split(':').first
|
|
88
|
+
# IPv6 bracket notation
|
|
89
|
+
elsif match = ip.match(/\[(\S+)\]/)
|
|
90
|
+
match.captures.first
|
|
91
|
+
# IPv6 bare notation
|
|
92
|
+
else
|
|
93
|
+
ip
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def geocoder_reject_non_ipv4_addresses(ip_addresses)
|
|
99
|
+
ips = []
|
|
100
|
+
for ip in ip_addresses
|
|
101
|
+
begin
|
|
102
|
+
valid_ip = IPAddr.new(ip)
|
|
103
|
+
rescue
|
|
104
|
+
valid_ip = false
|
|
105
|
+
end
|
|
106
|
+
ips << valid_ip.to_s if valid_ip
|
|
107
|
+
end
|
|
108
|
+
return ips.any? ? ips : ip_addresses
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
ActionDispatch::Request.__send__(:include, Geocoder::Request) if defined?(ActionDispatch::Request)
|
|
114
|
+
Rack::Request.__send__(:include, Geocoder::Request) if defined?(Rack::Request)
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
require 'geocoder/results/base'
|
|
2
|
+
|
|
3
|
+
module Geocoder
|
|
4
|
+
module Result
|
|
5
|
+
class AbstractApi < Base
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# Geolocation
|
|
9
|
+
|
|
10
|
+
def state
|
|
11
|
+
@data['region']
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def state_code
|
|
15
|
+
@data['region_iso_code']
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def city
|
|
19
|
+
@data["city"]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def city_geoname_id
|
|
23
|
+
@data["city_geoname_id"]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def region_geoname_id
|
|
27
|
+
@data["region_geoname_id"]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def postal_code
|
|
31
|
+
@data["postal_code"]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def country
|
|
35
|
+
@data["country"]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def country_code
|
|
39
|
+
@data["country_code"]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def country_geoname_id
|
|
43
|
+
@data["country_geoname_id"]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def country_is_eu
|
|
47
|
+
@data["country_is_eu"]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def continent
|
|
51
|
+
@data["continent"]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def continent_code
|
|
55
|
+
@data["continent_code"]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def continent_geoname_id
|
|
59
|
+
@data["continent_geoname_id"]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
##
|
|
63
|
+
# Security
|
|
64
|
+
|
|
65
|
+
def is_vpn?
|
|
66
|
+
@data.dig "security", "is_vpn"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
##
|
|
70
|
+
# Timezone
|
|
71
|
+
|
|
72
|
+
def timezone_name
|
|
73
|
+
@data.dig "timezone", "name"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def timezone_abbreviation
|
|
77
|
+
@data.dig "timezone", "abbreviation"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def timezone_gmt_offset
|
|
81
|
+
@data.dig "timezone", "gmt_offset"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def timezone_current_time
|
|
85
|
+
@data.dig "timezone", "current_time"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def timezone_is_dst
|
|
89
|
+
@data.dig "timezone", "is_dst"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
##
|
|
93
|
+
# Flag
|
|
94
|
+
|
|
95
|
+
def flag_emoji
|
|
96
|
+
@data.dig "flag", "emoji"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def flag_unicode
|
|
100
|
+
@data.dig "flag", "unicode"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def flag_png
|
|
104
|
+
@data.dig "flag", "png"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def flag_svg
|
|
108
|
+
@data.dig "flag", "svg"
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
##
|
|
112
|
+
# Currency
|
|
113
|
+
|
|
114
|
+
def currency_currency_name
|
|
115
|
+
@data.dig "currency", "currency_name"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def currency_currency_code
|
|
119
|
+
@data.dig "currency", "currency_code"
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
##
|
|
123
|
+
# Connection
|
|
124
|
+
|
|
125
|
+
def connection_autonomous_system_number
|
|
126
|
+
@data.dig "connection", "autonomous_system_number"
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def connection_autonomous_system_organization
|
|
130
|
+
@data.dig "connection", "autonomous_system_organization"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def connection_connection_type
|
|
134
|
+
@data.dig "connection", "connection_type"
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def connection_isp_name
|
|
138
|
+
@data.dig "connection", "isp_name"
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def connection_organization_name
|
|
142
|
+
@data.dig "connection", "organization_name"
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
require 'geocoder/results/base'
|
|
2
|
+
|
|
3
|
+
module Geocoder::Result
|
|
4
|
+
class Amap < Base
|
|
5
|
+
|
|
6
|
+
def coordinates
|
|
7
|
+
location = @data['location'] || @data['roadinters'].try(:first).try(:[], 'location') \
|
|
8
|
+
|| address_components.try(:[], 'streetNumber').try(:[], 'location')
|
|
9
|
+
location.to_s.split(",").reverse.map(&:to_f)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def address
|
|
13
|
+
formatted_address
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def state
|
|
17
|
+
province
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def province
|
|
21
|
+
address_components['province']
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def city
|
|
25
|
+
address_components['city'] == [] ? province : address_components["city"]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def district
|
|
29
|
+
address_components['district']
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def street
|
|
33
|
+
if address_components["neighborhood"]["name"] != []
|
|
34
|
+
return address_components["neighborhood"]["name"]
|
|
35
|
+
elsif address_components['township'] != []
|
|
36
|
+
return address_components["township"]
|
|
37
|
+
else
|
|
38
|
+
return @data['street'] || address_components['streetNumber'].try(:[], 'street')
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def street_number
|
|
43
|
+
@data['number'] || address_components['streetNumber'].try(:[], 'number')
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def formatted_address
|
|
47
|
+
@data['formatted_address']
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def address_components
|
|
51
|
+
@data['addressComponent'] || @data
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def state_code
|
|
55
|
+
""
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def postal_code
|
|
59
|
+
""
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def country
|
|
63
|
+
"China"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def country_code
|
|
67
|
+
"CN"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
##
|
|
71
|
+
# Get address components of a given type. Valid types are defined in
|
|
72
|
+
# Baidu's Geocoding API documentation and include (among others):
|
|
73
|
+
#
|
|
74
|
+
# :business
|
|
75
|
+
# :cityCode
|
|
76
|
+
#
|
|
77
|
+
def self.response_attributes
|
|
78
|
+
%w[roads pois roadinters]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
response_attributes.each do |a|
|
|
82
|
+
define_method a do
|
|
83
|
+
@data[a]
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require 'geocoder/results/base'
|
|
2
|
+
|
|
3
|
+
module Geocoder::Result
|
|
4
|
+
class AmazonLocationService < Base
|
|
5
|
+
def initialize(result)
|
|
6
|
+
@place = result.place
|
|
7
|
+
super
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def coordinates
|
|
11
|
+
[@place.geometry.point[1], @place.geometry.point[0]]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def address
|
|
15
|
+
@place.label
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def neighborhood
|
|
19
|
+
@place.neighborhood
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def route
|
|
23
|
+
@place.street
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def city
|
|
27
|
+
@place.municipality || @place.sub_region
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def state
|
|
31
|
+
@place.region
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def state_code
|
|
35
|
+
@place.region
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def province
|
|
39
|
+
@place.region
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def province_code
|
|
43
|
+
@place.region
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def postal_code
|
|
47
|
+
@place.postal_code
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def country
|
|
51
|
+
@place.country
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def country_code
|
|
55
|
+
@place.country
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def place_id
|
|
59
|
+
data.place_id if data.respond_to?(:place_id)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require 'geocoder/results/base'
|
|
2
|
+
|
|
3
|
+
module Geocoder::Result
|
|
4
|
+
class Azure < Base
|
|
5
|
+
def address
|
|
6
|
+
@data['address']['freeformAddress']
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def building_number
|
|
10
|
+
@data['address']['buildingNumber']
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def city
|
|
14
|
+
@data['address']['municipality']
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def coordinates
|
|
18
|
+
if @data['position'].is_a?(String) # reverse geocoding result
|
|
19
|
+
@data['position'].split(',').map(&:to_f)
|
|
20
|
+
elsif @data['position'].is_a?(Hash) # forward geocoding result
|
|
21
|
+
[@data['position']['lat'], @data['position']['lon']]
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def country
|
|
26
|
+
@data['address']['country']
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def country_code
|
|
30
|
+
@data['address']['countryCode']
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def district
|
|
34
|
+
@data['address']['municipalitySubdivision']
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def postal_code
|
|
38
|
+
@data['address']['postalCode']
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def province
|
|
42
|
+
@data['address']['countrySubdivision']
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def state
|
|
46
|
+
@data['address']['countrySubdivision']
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def state_code
|
|
50
|
+
@data['address']['countrySubdivisionCode']
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def street_name
|
|
54
|
+
@data['address']['streetName']
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def street_number
|
|
58
|
+
@data['address']['streetNumber']
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def viewport
|
|
62
|
+
@data['viewport'] || {}
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require 'geocoder/results/base'
|
|
2
|
+
|
|
3
|
+
module Geocoder::Result
|
|
4
|
+
class Baidu < Base
|
|
5
|
+
|
|
6
|
+
def coordinates
|
|
7
|
+
['lat', 'lng'].map{ |i| @data['location'][i] }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def province
|
|
11
|
+
@data['addressComponent'] and @data['addressComponent']['province'] or ""
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
alias_method :state, :province
|
|
15
|
+
|
|
16
|
+
def city
|
|
17
|
+
@data['addressComponent'] and @data['addressComponent']['city'] or ""
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def district
|
|
21
|
+
@data['addressComponent'] and @data['addressComponent']['district'] or ""
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def street
|
|
25
|
+
@data['addressComponent'] and @data['addressComponent']['street'] or ""
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def street_number
|
|
29
|
+
@data['addressComponent'] and @data['addressComponent']['street_number']
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def formatted_address
|
|
33
|
+
@data['formatted_address'] or ""
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
alias_method :address, :formatted_address
|
|
37
|
+
|
|
38
|
+
def address_components
|
|
39
|
+
@data['addressComponent']
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def state_code
|
|
43
|
+
""
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def postal_code
|
|
47
|
+
""
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def country
|
|
51
|
+
"China"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def country_code
|
|
55
|
+
"CN"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
##
|
|
59
|
+
# Get address components of a given type. Valid types are defined in
|
|
60
|
+
# Baidu's Geocoding API documentation and include (among others):
|
|
61
|
+
#
|
|
62
|
+
# :business
|
|
63
|
+
# :cityCode
|
|
64
|
+
#
|
|
65
|
+
def self.response_attributes
|
|
66
|
+
%w[business cityCode]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
response_attributes.each do |a|
|
|
70
|
+
define_method a do
|
|
71
|
+
@data[a]
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|