mini-safe-gem 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.
Files changed (175) hide show
  1. checksums.yaml +7 -0
  2. data/geocoder-1.8.6/CHANGELOG.md +669 -0
  3. data/geocoder-1.8.6/LICENSE +20 -0
  4. data/geocoder-1.8.6/README.md +827 -0
  5. data/geocoder-1.8.6/bin/console +13 -0
  6. data/geocoder-1.8.6/bin/geocode +5 -0
  7. data/geocoder-1.8.6/examples/app_defined_lookup_services.rb +22 -0
  8. data/geocoder-1.8.6/examples/cache_bypass.rb +48 -0
  9. data/geocoder-1.8.6/examples/reverse_geocode_job.rb +40 -0
  10. data/geocoder-1.8.6/lib/easting_northing.rb +319 -0
  11. data/geocoder-1.8.6/lib/generators/geocoder/config/config_generator.rb +14 -0
  12. data/geocoder-1.8.6/lib/generators/geocoder/config/templates/initializer.rb +27 -0
  13. data/geocoder-1.8.6/lib/generators/geocoder/maxmind/geolite_city_generator.rb +30 -0
  14. data/geocoder-1.8.6/lib/generators/geocoder/maxmind/geolite_country_generator.rb +30 -0
  15. data/geocoder-1.8.6/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb +30 -0
  16. data/geocoder-1.8.6/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb +17 -0
  17. data/geocoder-1.8.6/lib/generators/geocoder/migration_version.rb +15 -0
  18. data/geocoder-1.8.6/lib/geocoder/cache.rb +77 -0
  19. data/geocoder-1.8.6/lib/geocoder/cache_stores/base.rb +40 -0
  20. data/geocoder-1.8.6/lib/geocoder/cache_stores/generic.rb +35 -0
  21. data/geocoder-1.8.6/lib/geocoder/cache_stores/redis.rb +34 -0
  22. data/geocoder-1.8.6/lib/geocoder/calculations.rb +420 -0
  23. data/geocoder-1.8.6/lib/geocoder/cli.rb +121 -0
  24. data/geocoder-1.8.6/lib/geocoder/configuration.rb +151 -0
  25. data/geocoder-1.8.6/lib/geocoder/configuration_hash.rb +11 -0
  26. data/geocoder-1.8.6/lib/geocoder/esri_token.rb +38 -0
  27. data/geocoder-1.8.6/lib/geocoder/exceptions.rb +40 -0
  28. data/geocoder-1.8.6/lib/geocoder/ip_address.rb +36 -0
  29. data/geocoder-1.8.6/lib/geocoder/kernel_logger.rb +25 -0
  30. data/geocoder-1.8.6/lib/geocoder/logger.rb +47 -0
  31. data/geocoder-1.8.6/lib/geocoder/lookup.rb +155 -0
  32. data/geocoder-1.8.6/lib/geocoder/lookups/abstract_api.rb +46 -0
  33. data/geocoder-1.8.6/lib/geocoder/lookups/amap.rb +63 -0
  34. data/geocoder-1.8.6/lib/geocoder/lookups/amazon_location_service.rb +58 -0
  35. data/geocoder-1.8.6/lib/geocoder/lookups/azure.rb +56 -0
  36. data/geocoder-1.8.6/lib/geocoder/lookups/baidu.rb +63 -0
  37. data/geocoder-1.8.6/lib/geocoder/lookups/baidu_ip.rb +30 -0
  38. data/geocoder-1.8.6/lib/geocoder/lookups/ban_data_gouv_fr.rb +143 -0
  39. data/geocoder-1.8.6/lib/geocoder/lookups/base.rb +351 -0
  40. data/geocoder-1.8.6/lib/geocoder/lookups/bing.rb +82 -0
  41. data/geocoder-1.8.6/lib/geocoder/lookups/db_ip_com.rb +52 -0
  42. data/geocoder-1.8.6/lib/geocoder/lookups/esri.rb +114 -0
  43. data/geocoder-1.8.6/lib/geocoder/lookups/freegeoip.rb +62 -0
  44. data/geocoder-1.8.6/lib/geocoder/lookups/geoapify.rb +78 -0
  45. data/geocoder-1.8.6/lib/geocoder/lookups/geocoder_ca.rb +53 -0
  46. data/geocoder-1.8.6/lib/geocoder/lookups/geocodio.rb +42 -0
  47. data/geocoder-1.8.6/lib/geocoder/lookups/geoip2.rb +49 -0
  48. data/geocoder-1.8.6/lib/geocoder/lookups/geoportail_lu.rb +65 -0
  49. data/geocoder-1.8.6/lib/geocoder/lookups/google.rb +100 -0
  50. data/geocoder-1.8.6/lib/geocoder/lookups/google_places_details.rb +64 -0
  51. data/geocoder-1.8.6/lib/geocoder/lookups/google_places_search.rb +75 -0
  52. data/geocoder-1.8.6/lib/geocoder/lookups/google_premier.rb +61 -0
  53. data/geocoder-1.8.6/lib/geocoder/lookups/here.rb +73 -0
  54. data/geocoder-1.8.6/lib/geocoder/lookups/ip2location.rb +71 -0
  55. data/geocoder-1.8.6/lib/geocoder/lookups/ip2location_io.rb +62 -0
  56. data/geocoder-1.8.6/lib/geocoder/lookups/ip2location_lite.rb +40 -0
  57. data/geocoder-1.8.6/lib/geocoder/lookups/ipapi_com.rb +82 -0
  58. data/geocoder-1.8.6/lib/geocoder/lookups/ipbase.rb +49 -0
  59. data/geocoder-1.8.6/lib/geocoder/lookups/ipdata_co.rb +62 -0
  60. data/geocoder-1.8.6/lib/geocoder/lookups/ipgeolocation.rb +51 -0
  61. data/geocoder-1.8.6/lib/geocoder/lookups/ipinfo_io.rb +44 -0
  62. data/geocoder-1.8.6/lib/geocoder/lookups/ipinfo_io_lite.rb +42 -0
  63. data/geocoder-1.8.6/lib/geocoder/lookups/ipqualityscore.rb +50 -0
  64. data/geocoder-1.8.6/lib/geocoder/lookups/ipregistry.rb +68 -0
  65. data/geocoder-1.8.6/lib/geocoder/lookups/ipstack.rb +63 -0
  66. data/geocoder-1.8.6/lib/geocoder/lookups/latlon.rb +58 -0
  67. data/geocoder-1.8.6/lib/geocoder/lookups/location_iq.rb +54 -0
  68. data/geocoder-1.8.6/lib/geocoder/lookups/mapbox.rb +60 -0
  69. data/geocoder-1.8.6/lib/geocoder/lookups/mapquest.rb +58 -0
  70. data/geocoder-1.8.6/lib/geocoder/lookups/maxmind.rb +90 -0
  71. data/geocoder-1.8.6/lib/geocoder/lookups/maxmind_geoip2.rb +70 -0
  72. data/geocoder-1.8.6/lib/geocoder/lookups/maxmind_local.rb +71 -0
  73. data/geocoder-1.8.6/lib/geocoder/lookups/melissa_street.rb +41 -0
  74. data/geocoder-1.8.6/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
  75. data/geocoder-1.8.6/lib/geocoder/lookups/nominatim.rb +64 -0
  76. data/geocoder-1.8.6/lib/geocoder/lookups/opencagedata.rb +65 -0
  77. data/geocoder-1.8.6/lib/geocoder/lookups/osmnames.rb +57 -0
  78. data/geocoder-1.8.6/lib/geocoder/lookups/pc_miler.rb +87 -0
  79. data/geocoder-1.8.6/lib/geocoder/lookups/pdok_nl.rb +43 -0
  80. data/geocoder-1.8.6/lib/geocoder/lookups/pelias.rb +63 -0
  81. data/geocoder-1.8.6/lib/geocoder/lookups/photon.rb +89 -0
  82. data/geocoder-1.8.6/lib/geocoder/lookups/pickpoint.rb +41 -0
  83. data/geocoder-1.8.6/lib/geocoder/lookups/pointpin.rb +69 -0
  84. data/geocoder-1.8.6/lib/geocoder/lookups/postcode_anywhere_uk.rb +50 -0
  85. data/geocoder-1.8.6/lib/geocoder/lookups/postcodes_io.rb +31 -0
  86. data/geocoder-1.8.6/lib/geocoder/lookups/smarty_streets.rb +68 -0
  87. data/geocoder-1.8.6/lib/geocoder/lookups/telize.rb +75 -0
  88. data/geocoder-1.8.6/lib/geocoder/lookups/tencent.rb +59 -0
  89. data/geocoder-1.8.6/lib/geocoder/lookups/test.rb +49 -0
  90. data/geocoder-1.8.6/lib/geocoder/lookups/twogis.rb +58 -0
  91. data/geocoder-1.8.6/lib/geocoder/lookups/uk_ordnance_survey_names.rb +59 -0
  92. data/geocoder-1.8.6/lib/geocoder/lookups/yandex.rb +61 -0
  93. data/geocoder-1.8.6/lib/geocoder/models/active_record.rb +51 -0
  94. data/geocoder-1.8.6/lib/geocoder/models/base.rb +39 -0
  95. data/geocoder-1.8.6/lib/geocoder/models/mongo_base.rb +62 -0
  96. data/geocoder-1.8.6/lib/geocoder/models/mongo_mapper.rb +26 -0
  97. data/geocoder-1.8.6/lib/geocoder/models/mongoid.rb +32 -0
  98. data/geocoder-1.8.6/lib/geocoder/query.rb +125 -0
  99. data/geocoder-1.8.6/lib/geocoder/railtie.rb +26 -0
  100. data/geocoder-1.8.6/lib/geocoder/request.rb +114 -0
  101. data/geocoder-1.8.6/lib/geocoder/results/abstract_api.rb +146 -0
  102. data/geocoder-1.8.6/lib/geocoder/results/amap.rb +87 -0
  103. data/geocoder-1.8.6/lib/geocoder/results/amazon_location_service.rb +62 -0
  104. data/geocoder-1.8.6/lib/geocoder/results/azure.rb +65 -0
  105. data/geocoder-1.8.6/lib/geocoder/results/baidu.rb +75 -0
  106. data/geocoder-1.8.6/lib/geocoder/results/baidu_ip.rb +62 -0
  107. data/geocoder-1.8.6/lib/geocoder/results/ban_data_gouv_fr.rb +282 -0
  108. data/geocoder-1.8.6/lib/geocoder/results/base.rb +79 -0
  109. data/geocoder-1.8.6/lib/geocoder/results/bing.rb +52 -0
  110. data/geocoder-1.8.6/lib/geocoder/results/db_ip_com.rb +58 -0
  111. data/geocoder-1.8.6/lib/geocoder/results/esri.rb +78 -0
  112. data/geocoder-1.8.6/lib/geocoder/results/freegeoip.rb +40 -0
  113. data/geocoder-1.8.6/lib/geocoder/results/geoapify.rb +179 -0
  114. data/geocoder-1.8.6/lib/geocoder/results/geocoder_ca.rb +60 -0
  115. data/geocoder-1.8.6/lib/geocoder/results/geocodio.rb +78 -0
  116. data/geocoder-1.8.6/lib/geocoder/results/geoip2.rb +76 -0
  117. data/geocoder-1.8.6/lib/geocoder/results/geoportail_lu.rb +71 -0
  118. data/geocoder-1.8.6/lib/geocoder/results/google.rb +150 -0
  119. data/geocoder-1.8.6/lib/geocoder/results/google_places_details.rb +39 -0
  120. data/geocoder-1.8.6/lib/geocoder/results/google_places_search.rb +52 -0
  121. data/geocoder-1.8.6/lib/geocoder/results/google_premier.rb +6 -0
  122. data/geocoder-1.8.6/lib/geocoder/results/here.rb +77 -0
  123. data/geocoder-1.8.6/lib/geocoder/results/ip2location.rb +22 -0
  124. data/geocoder-1.8.6/lib/geocoder/results/ip2location_io.rb +21 -0
  125. data/geocoder-1.8.6/lib/geocoder/results/ip2location_lite.rb +47 -0
  126. data/geocoder-1.8.6/lib/geocoder/results/ipapi_com.rb +45 -0
  127. data/geocoder-1.8.6/lib/geocoder/results/ipbase.rb +40 -0
  128. data/geocoder-1.8.6/lib/geocoder/results/ipdata_co.rb +40 -0
  129. data/geocoder-1.8.6/lib/geocoder/results/ipgeolocation.rb +59 -0
  130. data/geocoder-1.8.6/lib/geocoder/results/ipinfo_io.rb +48 -0
  131. data/geocoder-1.8.6/lib/geocoder/results/ipinfo_io_lite.rb +16 -0
  132. data/geocoder-1.8.6/lib/geocoder/results/ipqualityscore.rb +54 -0
  133. data/geocoder-1.8.6/lib/geocoder/results/ipregistry.rb +304 -0
  134. data/geocoder-1.8.6/lib/geocoder/results/ipstack.rb +60 -0
  135. data/geocoder-1.8.6/lib/geocoder/results/latlon.rb +71 -0
  136. data/geocoder-1.8.6/lib/geocoder/results/location_iq.rb +6 -0
  137. data/geocoder-1.8.6/lib/geocoder/results/mapbox.rb +80 -0
  138. data/geocoder-1.8.6/lib/geocoder/results/mapquest.rb +48 -0
  139. data/geocoder-1.8.6/lib/geocoder/results/maxmind.rb +130 -0
  140. data/geocoder-1.8.6/lib/geocoder/results/maxmind_geoip2.rb +9 -0
  141. data/geocoder-1.8.6/lib/geocoder/results/maxmind_local.rb +44 -0
  142. data/geocoder-1.8.6/lib/geocoder/results/melissa_street.rb +46 -0
  143. data/geocoder-1.8.6/lib/geocoder/results/nationaal_georegister_nl.rb +62 -0
  144. data/geocoder-1.8.6/lib/geocoder/results/nominatim.rb +121 -0
  145. data/geocoder-1.8.6/lib/geocoder/results/opencagedata.rb +100 -0
  146. data/geocoder-1.8.6/lib/geocoder/results/osmnames.rb +56 -0
  147. data/geocoder-1.8.6/lib/geocoder/results/pc_miler.rb +98 -0
  148. data/geocoder-1.8.6/lib/geocoder/results/pdok_nl.rb +62 -0
  149. data/geocoder-1.8.6/lib/geocoder/results/pelias.rb +58 -0
  150. data/geocoder-1.8.6/lib/geocoder/results/photon.rb +119 -0
  151. data/geocoder-1.8.6/lib/geocoder/results/pickpoint.rb +6 -0
  152. data/geocoder-1.8.6/lib/geocoder/results/pointpin.rb +40 -0
  153. data/geocoder-1.8.6/lib/geocoder/results/postcode_anywhere_uk.rb +42 -0
  154. data/geocoder-1.8.6/lib/geocoder/results/postcodes_io.rb +40 -0
  155. data/geocoder-1.8.6/lib/geocoder/results/smarty_streets.rb +142 -0
  156. data/geocoder-1.8.6/lib/geocoder/results/telize.rb +40 -0
  157. data/geocoder-1.8.6/lib/geocoder/results/tencent.rb +72 -0
  158. data/geocoder-1.8.6/lib/geocoder/results/test.rb +33 -0
  159. data/geocoder-1.8.6/lib/geocoder/results/twogis.rb +76 -0
  160. data/geocoder-1.8.6/lib/geocoder/results/uk_ordnance_survey_names.rb +59 -0
  161. data/geocoder-1.8.6/lib/geocoder/results/yandex.rb +292 -0
  162. data/geocoder-1.8.6/lib/geocoder/sql.rb +110 -0
  163. data/geocoder-1.8.6/lib/geocoder/stores/active_record.rb +329 -0
  164. data/geocoder-1.8.6/lib/geocoder/stores/base.rb +115 -0
  165. data/geocoder-1.8.6/lib/geocoder/stores/mongo_base.rb +58 -0
  166. data/geocoder-1.8.6/lib/geocoder/stores/mongo_mapper.rb +13 -0
  167. data/geocoder-1.8.6/lib/geocoder/stores/mongoid.rb +13 -0
  168. data/geocoder-1.8.6/lib/geocoder/util.rb +29 -0
  169. data/geocoder-1.8.6/lib/geocoder/version.rb +3 -0
  170. data/geocoder-1.8.6/lib/geocoder.rb +48 -0
  171. data/geocoder-1.8.6/lib/maxmind_database.rb +109 -0
  172. data/geocoder-1.8.6/lib/tasks/geocoder.rake +54 -0
  173. data/geocoder-1.8.6/lib/tasks/maxmind.rake +73 -0
  174. data/mini-safe-gem.gemspec +12 -0
  175. metadata +214 -0
@@ -0,0 +1,351 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'uri'
4
+
5
+ unless defined?(ActiveSupport::JSON)
6
+ begin
7
+ require 'json'
8
+ rescue LoadError
9
+ raise LoadError, "Please install the 'json' or 'json_pure' gem to parse geocoder results."
10
+ end
11
+ end
12
+
13
+ module Geocoder
14
+ module Lookup
15
+
16
+ class Base
17
+ def initialize
18
+ @cache = nil
19
+ end
20
+
21
+ ##
22
+ # Human-readable name of the geocoding API.
23
+ #
24
+ def name
25
+ fail
26
+ end
27
+
28
+ ##
29
+ # Symbol which is used in configuration to refer to this Lookup.
30
+ #
31
+ def handle
32
+ str = self.class.to_s
33
+ str[str.rindex(':')+1..-1].gsub(/([a-z\d]+)([A-Z])/,'\1_\2').downcase.to_sym
34
+ end
35
+
36
+ ##
37
+ # Query the geocoding API and return a Geocoder::Result object.
38
+ # Returns +nil+ on timeout or error.
39
+ #
40
+ # Takes a search string (eg: "Mississippi Coast Coliseumf, Biloxi, MS",
41
+ # "205.128.54.202") for geocoding, or coordinates (latitude, longitude)
42
+ # for reverse geocoding. Returns an array of <tt>Geocoder::Result</tt>s.
43
+ #
44
+ def search(query, options = {})
45
+ query = Geocoder::Query.new(query, options) unless query.is_a?(Geocoder::Query)
46
+ results(query).map{ |r|
47
+ result = result_class.new(r)
48
+ result.cache_hit = @cache_hit if cache
49
+ result
50
+ }
51
+ end
52
+
53
+ ##
54
+ # Return the URL for a map of the given coordinates.
55
+ #
56
+ # Not necessarily implemented by all subclasses as only some lookups
57
+ # also provide maps.
58
+ #
59
+ def map_link_url(coordinates)
60
+ nil
61
+ end
62
+
63
+ ##
64
+ # Array containing string descriptions of keys required by the API.
65
+ # Empty array if keys are optional or not required.
66
+ #
67
+ def required_api_key_parts
68
+ []
69
+ end
70
+
71
+ ##
72
+ # URL to use for querying the geocoding engine.
73
+ #
74
+ # Subclasses should not modify this method. Instead they should define
75
+ # base_query_url and url_query_string. If absolutely necessary to
76
+ # subclss this method, they must also subclass #cache_key.
77
+ #
78
+ def query_url(query)
79
+ base_query_url(query) + url_query_string(query)
80
+ end
81
+
82
+ ##
83
+ # The working Cache object.
84
+ #
85
+ def cache
86
+ if @cache.nil? and store = configuration.cache
87
+ cache_options = configuration.cache_options
88
+ @cache = Cache.new(store, cache_options)
89
+ end
90
+ @cache
91
+ end
92
+
93
+ ##
94
+ # Array containing the protocols supported by the api.
95
+ # Should be set to [:http] if only HTTP is supported
96
+ # or [:https] if only HTTPS is supported.
97
+ #
98
+ def supported_protocols
99
+ [:http, :https]
100
+ end
101
+
102
+ private # -------------------------------------------------------------
103
+
104
+ ##
105
+ # String which, when concatenated with url_query_string(query)
106
+ # produces the full query URL. Should include the "?" a the end.
107
+ #
108
+ def base_query_url(query)
109
+ fail
110
+ end
111
+
112
+ ##
113
+ # An object with configuration data for this particular lookup.
114
+ #
115
+ def configuration
116
+ Geocoder.config_for_lookup(handle)
117
+ end
118
+
119
+ ##
120
+ # Object used to make HTTP requests.
121
+ #
122
+ def http_client
123
+ proxy_name = "#{protocol}_proxy"
124
+ if proxy = configuration.send(proxy_name)
125
+ proxy_url = !!(proxy =~ /^#{protocol}/) ? proxy : protocol + '://' + proxy
126
+ begin
127
+ uri = URI.parse(proxy_url)
128
+ rescue URI::InvalidURIError
129
+ raise ConfigurationError,
130
+ "Error parsing #{protocol.upcase} proxy URL: '#{proxy_url}'"
131
+ end
132
+ Net::HTTP::Proxy(uri.host, uri.port, uri.user, uri.password)
133
+ else
134
+ Net::HTTP
135
+ end
136
+ end
137
+
138
+ ##
139
+ # Geocoder::Result object or nil on timeout or other error.
140
+ #
141
+ def results(query)
142
+ fail
143
+ end
144
+
145
+ def query_url_params(query)
146
+ query.options[:params] || {}
147
+ end
148
+
149
+ def url_query_string(query)
150
+ hash_to_query(
151
+ query_url_params(query).reject{ |key,value| value.nil? }
152
+ )
153
+ end
154
+
155
+ ##
156
+ # Key to use for caching a geocoding result. Usually this will be the
157
+ # request URL, but in cases where OAuth is used and the nonce,
158
+ # timestamp, etc varies from one request to another, we need to use
159
+ # something else (like the URL before OAuth encoding).
160
+ #
161
+ def cache_key(query)
162
+ base_query_url(query) + hash_to_query(cache_key_params(query))
163
+ end
164
+
165
+ def cache_key_params(query)
166
+ # omit api_key and token because they may vary among requests
167
+ query_url_params(query).reject do |key,value|
168
+ key.to_s.match(/(key|token)/)
169
+ end
170
+ end
171
+
172
+ ##
173
+ # Class of the result objects
174
+ #
175
+ def result_class
176
+ Geocoder::Result.const_get(self.class.to_s.split(":").last)
177
+ end
178
+
179
+ ##
180
+ # Raise exception if configuration specifies it should be raised.
181
+ # Return false if exception not raised.
182
+ #
183
+ def raise_error(error, message = nil)
184
+ exceptions = configuration.always_raise
185
+ if exceptions == :all or exceptions.include?( error.is_a?(Class) ? error : error.class )
186
+ raise error, message
187
+ else
188
+ false
189
+ end
190
+ end
191
+
192
+ ##
193
+ # Returns a parsed search result (Ruby hash).
194
+ #
195
+ def fetch_data(query)
196
+ parse_raw_data fetch_raw_data(query)
197
+ rescue SocketError => err
198
+ raise_error(err) or Geocoder.log(:warn, "Geocoding API connection cannot be established.")
199
+ rescue Errno::ECONNREFUSED => err
200
+ raise_error(err) or Geocoder.log(:warn, "Geocoding API connection refused.")
201
+ rescue Geocoder::NetworkError => err
202
+ raise_error(err) or Geocoder.log(:warn, "Geocoding API connection is either unreacheable or reset by the peer")
203
+ rescue Timeout::Error => err
204
+ raise_error(err) or Geocoder.log(:warn, "Geocoding API not responding fast enough " +
205
+ "(use Geocoder.configure(:timeout => ...) to set limit).")
206
+ end
207
+
208
+ def parse_json(data)
209
+ if defined?(ActiveSupport::JSON)
210
+ ActiveSupport::JSON.decode(data)
211
+ else
212
+ JSON.parse(data)
213
+ end
214
+ rescue
215
+ unless raise_error(ResponseParseError.new(data))
216
+ Geocoder.log(:warn, "Geocoding API's response was not valid JSON")
217
+ Geocoder.log(:debug, "Raw response: #{data}")
218
+ end
219
+ end
220
+
221
+ ##
222
+ # Parses a raw search result (returns hash or array).
223
+ #
224
+ def parse_raw_data(raw_data)
225
+ parse_json(raw_data)
226
+ end
227
+
228
+ ##
229
+ # Protocol to use for communication with geocoding services.
230
+ # Set in configuration but not available for every service.
231
+ #
232
+ def protocol
233
+ "http" + (use_ssl? ? "s" : "")
234
+ end
235
+
236
+ def valid_response?(response)
237
+ (200..399).include?(response.code.to_i)
238
+ end
239
+
240
+ ##
241
+ # Fetch a raw geocoding result (JSON string).
242
+ # The result might or might not be cached.
243
+ #
244
+ def fetch_raw_data(query)
245
+ key = cache_key(query)
246
+ if cache and body = cache[key]
247
+ @cache_hit = true
248
+ else
249
+ check_api_key_configuration!(query)
250
+ response = make_api_request(query)
251
+ check_response_for_errors!(response)
252
+ body = response.body
253
+
254
+ # apply the charset from the Content-Type header, if possible
255
+ ct = response['content-type']
256
+
257
+ if ct && ct['charset']
258
+ charset = ct.split(';').select do |s|
259
+ s['charset']
260
+ end.first.to_s.split('=')
261
+ if charset.length == 2
262
+ body.force_encoding(charset.last) rescue ArgumentError
263
+ end
264
+ end
265
+
266
+ if cache and valid_response?(response)
267
+ cache[key] = body
268
+ end
269
+ @cache_hit = false
270
+ end
271
+ body
272
+ end
273
+
274
+ def check_response_for_errors!(response)
275
+ if response.code.to_i == 400
276
+ raise_error(Geocoder::InvalidRequest) ||
277
+ Geocoder.log(:warn, "Geocoding API error: 400 Bad Request")
278
+ elsif response.code.to_i == 401
279
+ raise_error(Geocoder::RequestDenied) ||
280
+ Geocoder.log(:warn, "Geocoding API error: 401 Unauthorized")
281
+ elsif response.code.to_i == 402
282
+ raise_error(Geocoder::OverQueryLimitError) ||
283
+ Geocoder.log(:warn, "Geocoding API error: 402 Payment Required")
284
+ elsif response.code.to_i == 429
285
+ raise_error(Geocoder::OverQueryLimitError) ||
286
+ Geocoder.log(:warn, "Geocoding API error: 429 Too Many Requests")
287
+ elsif response.code.to_i == 503
288
+ raise_error(Geocoder::ServiceUnavailable) ||
289
+ Geocoder.log(:warn, "Geocoding API error: 503 Service Unavailable")
290
+ end
291
+ end
292
+
293
+ ##
294
+ # Make an HTTP(S) request to a geocoding API and
295
+ # return the response object.
296
+ #
297
+ def make_api_request(query)
298
+ uri = URI.parse(query_url(query))
299
+ Geocoder.log(:debug, "Geocoder: HTTP request being made for #{uri.to_s}")
300
+ http_client.start(uri.host, uri.port, use_ssl: use_ssl?, open_timeout: configuration.timeout, read_timeout: configuration.timeout) do |client|
301
+ configure_ssl!(client) if use_ssl?
302
+ req = Net::HTTP::Get.new(uri.request_uri, configuration.http_headers)
303
+ if configuration.basic_auth[:user] and configuration.basic_auth[:password]
304
+ req.basic_auth(
305
+ configuration.basic_auth[:user],
306
+ configuration.basic_auth[:password]
307
+ )
308
+ end
309
+ client.request(req)
310
+ end
311
+ rescue Timeout::Error
312
+ raise Geocoder::LookupTimeout
313
+ rescue Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ENETUNREACH, Errno::ECONNRESET
314
+ raise Geocoder::NetworkError
315
+ end
316
+
317
+ def use_ssl?
318
+ if supported_protocols == [:https]
319
+ true
320
+ elsif supported_protocols == [:http]
321
+ false
322
+ else
323
+ configuration.use_https
324
+ end
325
+ end
326
+
327
+ def configure_ssl!(client); end
328
+
329
+ def check_api_key_configuration!(query)
330
+ key_parts = query.lookup.required_api_key_parts
331
+ if key_parts.size > Array(configuration.api_key).size
332
+ parts_string = key_parts.size == 1 ? key_parts.first : key_parts
333
+ raise Geocoder::ConfigurationError,
334
+ "The #{query.lookup.name} API requires a key to be configured: " +
335
+ parts_string.inspect
336
+ end
337
+ end
338
+
339
+ ##
340
+ # Simulate ActiveSupport's Object#to_query.
341
+ # Removes any keys with nil value.
342
+ #
343
+ def hash_to_query(hash)
344
+ require 'cgi' unless defined?(CGI) && defined?(CGI.escape)
345
+ hash.collect{ |p|
346
+ p[1].nil? ? nil : p.map{ |i| CGI.escape i.to_s } * '='
347
+ }.compact.sort * '&'
348
+ end
349
+ end
350
+ end
351
+ end
@@ -0,0 +1,82 @@
1
+ require 'geocoder/lookups/base'
2
+ require "geocoder/results/bing"
3
+
4
+ module Geocoder::Lookup
5
+ class Bing < Base
6
+
7
+ def name
8
+ "Bing"
9
+ end
10
+
11
+ def map_link_url(coordinates)
12
+ "http://www.bing.com/maps/default.aspx?cp=#{coordinates.join('~')}"
13
+ end
14
+
15
+ def required_api_key_parts
16
+ ["key"]
17
+ end
18
+
19
+ private # ---------------------------------------------------------------
20
+
21
+ def base_query_url(query)
22
+ text = ERB::Util.url_encode(query.sanitized_text.strip)
23
+ url = "#{protocol}://dev.virtualearth.net/REST/v1/Locations/"
24
+ if query.reverse_geocode?
25
+ url + "#{text}?"
26
+ else
27
+ if r = query.options[:region]
28
+ url << "#{r}/"
29
+ end
30
+ # use the more forgiving 'unstructured' query format to allow special
31
+ # chars, newlines, brackets, typos.
32
+ url + "?q=#{text}&"
33
+ end
34
+ end
35
+
36
+ def results(query)
37
+ return [] unless doc = fetch_data(query)
38
+
39
+ if doc['statusCode'] == 200
40
+ return doc['resourceSets'].first['estimatedTotal'] > 0 ? doc['resourceSets'].first['resources'] : []
41
+ elsif doc['statusCode'] == 401 and doc["authenticationResultCode"] == "InvalidCredentials"
42
+ raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "Invalid Bing API key.")
43
+ elsif doc['statusCode'] == 403
44
+ raise_error(Geocoder::RequestDenied) || Geocoder.log(:warn, "Bing Geocoding API error: Forbidden Request")
45
+ elsif [500, 503].include?(doc['statusCode'])
46
+ raise_error(Geocoder::ServiceUnavailable) ||
47
+ Geocoder.log(:warn, "Bing Geocoding API error: Service Unavailable")
48
+ else
49
+ Geocoder.log(:warn, "Bing Geocoding API error: #{doc['statusCode']} (#{doc['statusDescription']}).")
50
+ end
51
+ return []
52
+ end
53
+
54
+ def query_url_params(query)
55
+ {
56
+ key: configuration.api_key,
57
+ culture: (query.language || configuration.language)
58
+ }.merge(super)
59
+ end
60
+
61
+ def check_response_for_errors!(response)
62
+ super
63
+ if server_overloaded?(response)
64
+ raise_error(Geocoder::ServiceUnavailable) ||
65
+ Geocoder.log(:warn, "Bing Geocoding API error: Service Unavailable")
66
+ end
67
+ end
68
+
69
+ def valid_response?(response)
70
+ super(response) and not server_overloaded?(response)
71
+ end
72
+
73
+ def server_overloaded?(response)
74
+ # Occasionally, the servers processing service requests can be overloaded,
75
+ # and you may receive some responses that contain no results for queries that
76
+ # you would normally receive a result. To identify this situation,
77
+ # check the HTTP headers of the response. If the HTTP header X-MS-BM-WS-INFO is set to 1,
78
+ # it is best to wait a few seconds and try again.
79
+ response['x-ms-bm-ws-info'].to_i == 1
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,52 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/db_ip_com'
3
+
4
+ module Geocoder::Lookup
5
+ class DbIpCom < Base
6
+
7
+ def name
8
+ 'DB-IP.com'
9
+ end
10
+
11
+ def supported_protocols
12
+ [:https, :http]
13
+ end
14
+
15
+ def required_api_key_parts
16
+ ['api_key']
17
+ end
18
+
19
+ private # ----------------------------------------------------------------
20
+
21
+ def base_query_url(query)
22
+ "#{protocol}://api.db-ip.com/v2/#{configuration.api_key}/#{query.sanitized_text}?"
23
+ end
24
+
25
+ ##
26
+ # Same as query_url but without the api key.
27
+ #
28
+ def cache_key(query)
29
+ "#{protocol}://api.db-ip.com/v2/#{query.sanitized_text}?" + hash_to_query(cache_key_params(query))
30
+ end
31
+
32
+ def results(query)
33
+ return [] unless (doc = fetch_data(query))
34
+
35
+ case doc['error']
36
+ when 'maximum number of queries per day exceeded'
37
+ raise_error Geocoder::OverQueryLimitError ||
38
+ Geocoder.log(:warn, 'DB-API query limit exceeded.')
39
+
40
+ when 'invalid API key'
41
+ raise_error Geocoder::InvalidApiKey ||
42
+ Geocoder.log(:warn, 'Invalid DB-IP API key.')
43
+ when nil
44
+ [doc]
45
+
46
+ else
47
+ raise_error Geocoder::Error ||
48
+ Geocoder.log(:warn, "Request failed: #{doc['error']}")
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,114 @@
1
+ require 'geocoder/lookups/base'
2
+ require "geocoder/results/esri"
3
+ require 'geocoder/esri_token'
4
+
5
+ module Geocoder::Lookup
6
+ class Esri < Base
7
+
8
+ def name
9
+ "Esri"
10
+ end
11
+
12
+ def supported_protocols
13
+ [:https]
14
+ end
15
+
16
+ private # ---------------------------------------------------------------
17
+
18
+ def base_query_url(query)
19
+ action = query.reverse_geocode? ? "reverseGeocode" : "find"
20
+ "#{protocol}://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/#{action}?"
21
+ end
22
+
23
+ def results(query)
24
+ return [] unless doc = fetch_data(query)
25
+
26
+ if (doc['error'].nil?)
27
+ if (!query.reverse_geocode?)
28
+ return [] if !doc['locations'] || doc['locations'].empty?
29
+ end
30
+ return [ doc ]
31
+ else
32
+ case [ doc['error']['code'] ]
33
+ when [498]
34
+ raise_error(Geocoder::InvalidApiKey, doc['error']['message']) ||
35
+ Geocoder.log(:warn, "#{self.name} Geocoding API error: #{doc['error']['message']}")
36
+ when [ 403 ]
37
+ raise_error(Geocoder::RequestDenied, 'ESRI request denied') ||
38
+ Geocoder.log(:warn, "#{self.name} ESRI request denied: #{doc['error']['message']}")
39
+ when [ 500 ], [501]
40
+ raise_error(Geocoder::ServiceUnavailable, 'ESRI service unavailable') ||
41
+ Geocoder.log(:warn, "#{self.name} ESRI service error: #{doc['error']['message']}")
42
+ else
43
+ raise_error(Geocoder::Error, doc['error']['message']) ||
44
+ Geocoder.log(:warn, "#{self.name} Geocoding error: #{doc['error']['message']}")
45
+ end
46
+ end
47
+ return []
48
+ end
49
+
50
+ def query_url_params(query)
51
+ params = {
52
+ :f => "pjson",
53
+ :outFields => "*"
54
+ }
55
+ if query.reverse_geocode?
56
+ params[:location] = query.coordinates.reverse.join(',')
57
+ else
58
+ params[:text] = query.sanitized_text
59
+ end
60
+
61
+ params[:token] = token(query)
62
+
63
+ if for_storage_value = for_storage(query)
64
+ params[:forStorage] = for_storage_value
65
+ end
66
+ params[:sourceCountry] = configuration[:source_country] if configuration[:source_country]
67
+ params[:preferredLabelValues] = configuration[:preferred_label_values] if configuration[:preferred_label_values]
68
+
69
+ params.merge(super)
70
+ end
71
+
72
+ def for_storage(query)
73
+ if query.options.has_key?(:for_storage)
74
+ query.options[:for_storage]
75
+ else
76
+ configuration[:for_storage]
77
+ end
78
+ end
79
+
80
+ def token(query)
81
+ token_instance = if query.options[:token]
82
+ query.options[:token]
83
+ else
84
+ configuration[:token]
85
+ end
86
+
87
+ if !valid_token_configured?(token_instance) && configuration.api_key
88
+ token_instance = create_and_save_token!(query)
89
+ end
90
+
91
+ token_instance.to_s unless token_instance.nil?
92
+ end
93
+
94
+ def valid_token_configured?(token_instance)
95
+ !token_instance.nil? && token_instance.active?
96
+ end
97
+
98
+ def create_and_save_token!(query)
99
+ token_instance = create_token
100
+
101
+ if query.options[:token]
102
+ query.options[:token] = token_instance
103
+ else
104
+ Geocoder.merge_into_lookup_config(:esri, token: token_instance)
105
+ end
106
+
107
+ token_instance
108
+ end
109
+
110
+ def create_token
111
+ Geocoder::EsriToken.generate_token(*configuration.api_key)
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,62 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/freegeoip'
3
+
4
+ module Geocoder::Lookup
5
+ class Freegeoip < Base
6
+
7
+ def name
8
+ "FreeGeoIP"
9
+ end
10
+
11
+ def supported_protocols
12
+ if configuration[:host]
13
+ [:https]
14
+ else
15
+ # use https for default host
16
+ [:https]
17
+ end
18
+ end
19
+
20
+ private # ---------------------------------------------------------------
21
+
22
+ def base_query_url(query)
23
+ "#{protocol}://#{host}/json/#{query.sanitized_text}?"
24
+ end
25
+
26
+ def query_url_params(query)
27
+ {
28
+ :apikey => configuration.api_key
29
+ }.merge(super)
30
+ end
31
+
32
+ def parse_raw_data(raw_data)
33
+ raw_data.match(/^<html><title>404/) ? nil : super(raw_data)
34
+ end
35
+
36
+ def results(query)
37
+ # don't look up a loopback or private address, just return the stored result
38
+ return [reserved_result(query.text)] if query.internal_ip_address?
39
+ # note: Freegeoip.net returns plain text "Not Found" on bad request
40
+ (doc = fetch_data(query)) ? [doc] : []
41
+ end
42
+
43
+ def reserved_result(ip)
44
+ {
45
+ "ip" => ip,
46
+ "city" => "",
47
+ "region_code" => "",
48
+ "region_name" => "",
49
+ "metro_code" => "",
50
+ "zip_code" => "",
51
+ "latitude" => "0",
52
+ "longitude" => "0",
53
+ "country_name" => "Reserved",
54
+ "country_code" => "RD"
55
+ }
56
+ end
57
+
58
+ def host
59
+ configuration[:host] || "freegeoip.app"
60
+ end
61
+ end
62
+ end