geokit 1.7.0.rc1 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,43 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://yboss.yahooapis.com/geo/placefinder?flags=J&oauth_consumer_key=dj0yJmk9cXByQVN2WHZmTVhDJmQ9WVdrOVZscG1WVWhOTldrbWNHbzlNakF6TlRJME16UTJNZy0tJnM9Y29uc3VtZXJzZWNyZXQmeD0zNg--&oauth_nonce=731410e6df&oauth_signature=%2Bde/2eYXvMPhoRu5MUdjhPct3xY=&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1384355278&oauth_version=1.0&q=San%20Francisco,%20CA
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - '*/*'
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Date:
22
+ - Wed, 13 Nov 2013 15:08:00 GMT
23
+ P3p:
24
+ - policyref="http://info.yahoo.com/w3c/p3p.xml", CP="CAO DSP COR CUR ADM DEV
25
+ TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY
26
+ ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE LOC GOV"
27
+ Vary:
28
+ - Accept-Encoding
29
+ Transfer-Encoding:
30
+ - chunked
31
+ Content-Type:
32
+ - application/json
33
+ Cache-Control:
34
+ - private
35
+ body:
36
+ encoding: UTF-8
37
+ string: '{"bossresponse":{"responsecode":"200","placefinder":{"start":"0","count":"1","request":"flags=J&q=San%20Francisco%2C%20CA","results":[{"quality":"40","latitude":"37.77713","longitude":"-122.41964","offsetlat":"37.77713","offsetlon":"-122.41964","radius":"8800","name":"","line1":"","line2":"San
38
+ Francisco, CA","line3":"","line4":"United States","house":"","street":"","xstreet":"","unittype":"","unit":"","postal":"","neighborhood":"","city":"San
39
+ Francisco","county":"San Francisco County","state":"California","country":"United
40
+ States","countrycode":"US","statecode":"CA","countycode":"","uzip":"94102","hash":"","woeid":"2487956","woetype":"7"}]}}}'
41
+ http_version:
42
+ recorded_at: Wed, 13 Nov 2013 15:07:58 GMT
43
+ recorded_with: VCR 2.7.0
@@ -0,0 +1,44 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://yboss.yahooapis.com/geo/placefinder?flags=J&oauth_consumer_key=dj0yJmk9cXByQVN2WHZmTVhDJmQ9WVdrOVZscG1WVWhOTldrbWNHbzlNakF6TlRJME16UTJNZy0tJnM9Y29uc3VtZXJzZWNyZXQmeD0zNg--&oauth_nonce=7a0ce94e38&oauth_signature=aTamhmDusxM4xYZXWocDEb5YmyE=&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1384355278&oauth_version=1.0&q=100%20Spear%20St,%20San%20Francisco,%20CA,%2094105-1522,%20US
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - '*/*'
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Date:
22
+ - Wed, 13 Nov 2013 15:08:01 GMT
23
+ P3p:
24
+ - policyref="http://info.yahoo.com/w3c/p3p.xml", CP="CAO DSP COR CUR ADM DEV
25
+ TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY
26
+ ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE LOC GOV"
27
+ Vary:
28
+ - Accept-Encoding
29
+ Transfer-Encoding:
30
+ - chunked
31
+ Content-Type:
32
+ - application/json
33
+ Cache-Control:
34
+ - private
35
+ body:
36
+ encoding: UTF-8
37
+ string: '{"bossresponse":{"responsecode":"200","placefinder":{"start":"0","count":"1","request":"flags=J&q=100%20Spear%20St%2C%20San%20Francisco%2C%20CA%2C%2094105-1522%2C%20US","results":[{"quality":"87","latitude":"37.792332","longitude":"-122.393791","offsetlat":"37.792198","offsetlon":"-122.393898","radius":"400","name":"","line1":"100
38
+ Spear St","line2":"San Francisco, CA 94105-1578","line3":"","line4":"United
39
+ States","house":"100","street":"Spear St","xstreet":"","unittype":"","unit":"","postal":"94105-1578","neighborhood":"","city":"San
40
+ Francisco","county":"San Francisco County","state":"California","country":"United
41
+ States","countrycode":"US","statecode":"CA","countycode":"","uzip":"94105","hash":"0FA06819B5F53E75","woeid":"12797156","woetype":"11"}]}}}'
42
+ http_version:
43
+ recorded_at: Wed, 13 Nov 2013 15:07:59 GMT
44
+ recorded_with: VCR 2.7.0
@@ -0,0 +1,40 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://yboss.yahooapis.com/geo/placefinder?flags=J&oauth_consumer_key=dj0yJmk9cXByQVN2WHZmTVhDJmQ9WVdrOVZscG1WVWhOTldrbWNHbzlNakF6TlRJME16UTJNZy0tJnM9Y29uc3VtZXJzZWNyZXQmeD0zNg--&oauth_nonce=2c5ad2f846&oauth_signature=h2eR3b0GSWsgqU2nJhd1jPP8ihI=&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1384355895&oauth_version=1.0&q=ZZ,%20ZZ,%20ZZ
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - '*/*'
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Date:
22
+ - Wed, 13 Nov 2013 15:18:19 GMT
23
+ P3p:
24
+ - policyref="http://info.yahoo.com/w3c/p3p.xml", CP="CAO DSP COR CUR ADM DEV
25
+ TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY
26
+ ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE LOC GOV"
27
+ Vary:
28
+ - Accept-Encoding
29
+ Transfer-Encoding:
30
+ - chunked
31
+ Content-Type:
32
+ - application/json
33
+ Cache-Control:
34
+ - private
35
+ body:
36
+ encoding: UTF-8
37
+ string: '{"bossresponse":{"responsecode":"200","placefinder":{"start":"0","count":"0","request":"flags=J&q=ZZ%2C%20ZZ%2C%20ZZ"}}}'
38
+ http_version:
39
+ recorded_at: Wed, 13 Nov 2013 15:18:16 GMT
40
+ recorded_with: VCR 2.7.0
data/geokit.gemspec CHANGED
@@ -10,13 +10,12 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ["michael+geokit@noack.com.au"]
11
11
  spec.description = %q{Geokit provides geocoding and distance calculation in an easy-to-use API}
12
12
  spec.summary = %q{Geokit: encoding and distance calculation gem}
13
- spec.homepage = "http://geokit.org"
13
+ spec.homepage = "http://github.com/geokit/geokit"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.has_rdoc = true
17
17
  spec.rdoc_options = ["--main", "README.markdown"]
18
18
  spec.extra_rdoc_files = ["README.markdown"]
19
- spec.extensions = 'ext/mkrf_conf.rb'
20
19
 
21
20
  spec.files = `git ls-files`.split($/)
22
21
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
@@ -29,5 +28,7 @@ Gem::Specification.new do |spec|
29
28
  spec.add_development_dependency "simplecov-rcov"
30
29
  spec.add_development_dependency 'rake'
31
30
  spec.add_development_dependency 'mocha'
31
+ spec.add_development_dependency 'coveralls'
32
+ spec.add_development_dependency 'vcr'
33
+ spec.add_development_dependency 'webmock' # used in vcr
32
34
  end
33
-
@@ -38,7 +38,9 @@ module Geokit
38
38
  @@proxy_user = nil
39
39
  @@proxy_pass = nil
40
40
  @@request_timeout = nil
41
- @@yahoo = 'REPLACE_WITH_YOUR_YAHOO_KEY'
41
+ @@yahoo_consumer_key = 'REPLACE_WITH_YOUR_YAHOO_BOSS_OAUTH_CONSUMER_KEY'
42
+ @@yahoo_consumer_secret = 'REPLACE_WITH_YOUR_YAHOO_BOSS_OAUTH_CONSUMER_SECRET'
43
+ @@yandex = 'REPLACE_WITH_YOUR_YANDEX_KEY'
42
44
  @@google = 'REPLACE_WITH_YOUR_GOOGLE_KEY'
43
45
  @@google_client_id = nil
44
46
  @@google_cryptographic_key = nil
@@ -133,10 +135,11 @@ module Geokit
133
135
  uri = URI.parse(url)
134
136
  req = Net::HTTP::Get.new(url)
135
137
  req.basic_auth(uri.user, uri.password) if uri.userinfo
136
- res = Net::HTTP::Proxy(GeoKit::Geocoders::proxy_addr,
138
+ res = Net::HTTP::new(uri.host, uri.port,
139
+ GeoKit::Geocoders::proxy_addr,
137
140
  GeoKit::Geocoders::proxy_port,
138
141
  GeoKit::Geocoders::proxy_user,
139
- GeoKit::Geocoders::proxy_pass).start(uri.host, uri.port) { |http| http.get(uri.path + "?" + uri.query) }
142
+ GeoKit::Geocoders::proxy_pass).start { |http| http.request(req) }
140
143
  return res
141
144
  end
142
145
 
@@ -237,11 +237,6 @@ module Geokit
237
237
  @lng=lng.to_f if lng
238
238
  end
239
239
 
240
- def ll=(hash)
241
- self.lat = hash['lat']
242
- self.lng = hash['lng']
243
- end
244
-
245
240
  # Returns the lat and lng attributes as a comma-separated string.
246
241
  def ll
247
242
  "#{lat},#{lng}"
@@ -10,7 +10,7 @@ module Geokit
10
10
  res = self.call_geocoder_service(submit_url)
11
11
  return GeoLoc.new unless (res.is_a?(Net::HTTPSuccess) || res.is_a?(Net::HTTPOK))
12
12
  json = res.body
13
- logger.debug "Google reverse-geocoding. LL: #{latlng}. Result: #{json}"
13
+ logger.debug "Google reverse-geocoding. LL: #{latlng}. Result: #{CGI.escape(json)}"
14
14
  return self.json2GeoLoc(json)
15
15
  end
16
16
 
@@ -41,14 +41,15 @@ module Geokit
41
41
  # Geokit::Geocoders::GoogleGeocoder.geocode('Winnetka', :bias => bounds).state # => 'CA'
42
42
  def self.do_geocode(address, options = {})
43
43
  bias_str = options[:bias] ? construct_bias_string_from_options(options[:bias]) : ''
44
+ language_str = options[:language] ? "&language=#{options[:language]}" : ''
44
45
  address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
45
- submit_url = submit_url("/maps/api/geocode/json?sensor=false&address=#{Geokit::Inflector::url_escape(address_str)}#{bias_str}")
46
+ submit_url = submit_url("/maps/api/geocode/json?sensor=false&address=#{Geokit::Inflector::url_escape(address_str)}#{bias_str}#{language_str}")
46
47
 
47
48
  res = self.call_geocoder_service(submit_url)
48
49
  return GeoLoc.new if !res.is_a?(Net::HTTPSuccess)
49
50
 
50
51
  json = res.body
51
- logger.debug "Google geocoding. Address: #{address}. Result: #{json}"
52
+ logger.debug "Google geocoding. Address: #{address}. Result: #{CGI.escape(json)}"
52
53
 
53
54
  return self.json2GeoLoc(json, address)
54
55
  end
@@ -85,7 +86,8 @@ module Geokit
85
86
  "&region=#{bias.to_s.downcase}"
86
87
  when Bounds
87
88
  # viewport biasing
88
- Geokit::Inflector::url_escape("&bounds=#{bias.sw.to_s}|#{bias.ne.to_s}")
89
+ url_escaped_string = Geokit::Inflector::url_escape("#{bias.sw.to_s}|#{bias.ne.to_s}")
90
+ "&bounds=#{url_escaped_string}"
89
91
  end
90
92
  end
91
93
 
@@ -180,12 +182,17 @@ module Geokit
180
182
  res.accuracy = 7
181
183
  end
182
184
 
183
- res.ll = addr['geometry']['location']
184
-
185
- ne = Geokit::LatLng.new
186
- ne.ll = addr['geometry']['viewport']['northeast']
187
- sw = Geokit::LatLng.new
188
- sw.ll = addr['geometry']['viewport']['southwest']
185
+ res.lat=addr['geometry']['location']['lat'].to_f
186
+ res.lng=addr['geometry']['location']['lng'].to_f
187
+
188
+ ne=Geokit::LatLng.new(
189
+ addr['geometry']['viewport']['northeast']['lat'].to_f,
190
+ addr['geometry']['viewport']['northeast']['lng'].to_f
191
+ )
192
+ sw=Geokit::LatLng.new(
193
+ addr['geometry']['viewport']['southwest']['lat'].to_f,
194
+ addr['geometry']['viewport']['southwest']['lng'].to_f
195
+ )
189
196
  res.suggested_bounds = Geokit::Bounds.new(sw,ne)
190
197
 
191
198
  res
@@ -57,7 +57,7 @@ module Geokit
57
57
  res = GeoLoc.new
58
58
  res.provider = 'hostip'
59
59
  res.city, res.state = yaml['City'].split(', ')
60
- country, res.country_code = yaml['Country'].split(' (')
60
+ res.country, res.country_code = yaml['Country'].split(' (')
61
61
  res.lat = yaml['Latitude']
62
62
  res.lng = yaml['Longitude']
63
63
  res.country_code.chop!
@@ -0,0 +1,41 @@
1
+ require "geoip"
2
+
3
+ module Geokit
4
+ module Geocoders
5
+
6
+ @@geoip_data_path = File.expand_path(File.join(File.dirname(__FILE__),'../../..','data','GeoLiteCity.dat'))
7
+ __define_accessors
8
+
9
+ # Provides geocoding based upon an IP address. The underlying web service is MaxMind
10
+ class MaxmindGeocoder < Geocoder
11
+ private
12
+
13
+ def self.do_geocode(ip, options = {})
14
+ # return GeoLoc.new unless /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?$/.match(ip)
15
+ return maxmind(ip)
16
+ rescue
17
+ logger.error "Caught an error during MaxMind geocoding call: " + $!.to_s
18
+ return GeoLoc.new
19
+ end
20
+
21
+
22
+ def self.maxmind(ip)
23
+ res = GeoIP.new(Geokit::Geocoders::geoip_data_path).city(ip)
24
+
25
+ loc = GeoLoc.new(
26
+ :provider => 'maxmind_city',
27
+ :lat => res.latitude,
28
+ :lng => res.longitude,
29
+ :city => res.city_name,
30
+ :state => res.region_name,
31
+ :zip => res.postal_code,
32
+ :country_code => res.country_code3
33
+ )
34
+
35
+ # loc.success = res.city_name && res.city_name != ''
36
+ loc.success = (res.longitude > 0 && res.latitude > 0)
37
+ return loc
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,32 @@
1
+ module Geokit
2
+ module Geocoders
3
+ # Provides geocoding based upon an IP address. The underlying web service is geoplugin.net
4
+ class RipeGeocoder < Geocoder
5
+ private
6
+
7
+ def self.do_geocode(ip, options = {})
8
+ return GeoLoc.new unless /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?$/.match(ip)
9
+ response = self.call_geocoder_service("http://stat.ripe.net/data/geoloc/data.json?resource=#{ip}")
10
+ return response.is_a?(Net::HTTPSuccess) ? parse_json(response.body) : GeoLoc.new
11
+ rescue
12
+ logger.error "Caught an error during GeoPluginGeocoder geocoding call: #{$!}"
13
+ return GeoLoc.new
14
+ end
15
+
16
+ def self.parse_json(json)
17
+ json = MultiJson.load(json)
18
+ geo = GeoLoc.new
19
+ data = json['data']['locations'][0]
20
+
21
+ geo.provider='RIPE'
22
+ geo.city = data['city']
23
+ geo.country_code = data['country']
24
+ geo.lat = data['latitude']
25
+ geo.lng = data['longitude']
26
+ geo.success = (data['status_code'] == 200)
27
+ return geo
28
+ end
29
+ end
30
+
31
+ end
32
+ end
@@ -5,12 +5,21 @@ module Geokit
5
5
  class YahooGeocoder < Geocoder
6
6
 
7
7
  private
8
+ def self.submit_url(query_string)
9
+ o = OauthUtil.new
10
+ o.consumer_key = Geocoders::yahoo_consumer_key
11
+ o.consumer_secret = Geocoders::yahoo_consumer_secret
12
+ base = "http://yboss.yahooapis.com/geo/placefinder"
13
+ parsed_url = URI.parse("#{base}#{query_string}")
14
+ "http://yboss.yahooapis.com/geo/placefinder?#{o.sign(parsed_url).query_string}"
15
+ end
8
16
 
9
17
  # Template method which does the geocode lookup.
10
18
  def self.do_geocode(address, options = {})
11
19
  address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
12
- url="http://where.yahooapis.com/geocode?flags=J&appid=#{Geokit::Geocoders::yahoo}&q=#{Geokit::Inflector::url_escape(address_str)}"
13
- res = self.call_geocoder_service(url)
20
+ submit_url = submit_url("?q=#{Geokit::Inflector::url_escape(address_str)}&flags=J")
21
+
22
+ res = self.call_geocoder_service(submit_url)
14
23
  return GeoLoc.new if !res.is_a?(Net::HTTPSuccess)
15
24
  json = res.body
16
25
  logger.debug "Yahoo geocoding. Address: #{address}. Result: #{json}"
@@ -20,9 +29,9 @@ module Geokit
20
29
  def self.json2GeoLoc(json, address)
21
30
  results = MultiJson.load(json)
22
31
 
23
- if results['ResultSet']['Error'] == 0 && results['ResultSet']['Results'] != nil && results['ResultSet']['Results'].first != nil
32
+ if results && results['bossresponse'] && results['bossresponse']['placefinder'] && results['bossresponse']['placefinder']['results'] && results['bossresponse']['placefinder']['results'].first != nil
24
33
  geoloc = nil
25
- results['ResultSet']['Results'].each do |result|
34
+ results['bossresponse']['placefinder']['results'].each do |result|
26
35
  extracted_geoloc = extract_geoloc(result)
27
36
  if geoloc.nil?
28
37
  geoloc = extracted_geoloc
@@ -52,7 +61,7 @@ module Geokit
52
61
  geoloc.state = geoloc.is_us? ? result_json['statecode'] : result_json['state']
53
62
  geoloc.zip = result_json['postal']
54
63
 
55
- geoloc.precision = case result_json['quality']
64
+ geoloc.precision = case result_json['quality'].to_i
56
65
  when 9,10 then 'country'
57
66
  when 19..30 then 'state'
58
67
  when 39,40 then 'city'
@@ -73,3 +82,114 @@ module Geokit
73
82
  end
74
83
  end
75
84
  end
85
+
86
+ # Oauth Util
87
+ # from gist: https://gist.github.com/erikeldridge/383159
88
+ # A utility for signing an url using OAuth in a way that's convenient for debugging
89
+ # Note: the standard Ruby OAuth lib is here http://github.com/mojodna/oauth
90
+ # License: http://gist.github.com/375593
91
+ # Usage: see example.rb below
92
+
93
+ require 'uri'
94
+ require 'cgi'
95
+ require 'openssl'
96
+ require 'base64'
97
+
98
+ class OauthUtil
99
+
100
+ attr_accessor :consumer_key, :consumer_secret, :token, :token_secret, :req_method,
101
+ :sig_method, :oauth_version, :callback_url, :params, :req_url, :base_str
102
+
103
+ def initialize
104
+ @consumer_key = ''
105
+ @consumer_secret = ''
106
+ @token = ''
107
+ @token_secret = ''
108
+ @req_method = 'GET'
109
+ @sig_method = 'HMAC-SHA1'
110
+ @oauth_version = '1.0'
111
+ @callback_url = ''
112
+ end
113
+
114
+ # openssl::random_bytes returns non-word chars, which need to be removed. using alt method to get length
115
+ # ref http://snippets.dzone.com/posts/show/491
116
+ def nonce
117
+ Array.new( 5 ) { rand(256) }.pack('C*').unpack('H*').first
118
+ end
119
+
120
+ def percent_encode( string )
121
+
122
+ # ref http://snippets.dzone.com/posts/show/1260
123
+ return URI.escape( string, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]") ).gsub('*', '%2A')
124
+ end
125
+
126
+ # @ref http://oauth.net/core/1.0/#rfc.section.9.2
127
+ def signature
128
+ key = percent_encode( @consumer_secret ) + '&' + percent_encode( @token_secret )
129
+
130
+ # ref: http://blog.nathanielbibler.com/post/63031273/openssl-hmac-vs-ruby-hmac-benchmarks
131
+ digest = OpenSSL::Digest::Digest.new( 'sha1' )
132
+ hmac = OpenSSL::HMAC.digest( digest, key, @base_str )
133
+
134
+ # ref http://groups.google.com/group/oauth-ruby/browse_thread/thread/9110ed8c8f3cae81
135
+ Base64.encode64( hmac ).chomp.gsub( /\n/, '' )
136
+ end
137
+
138
+ # sort (very important as it affects the signature), concat, and percent encode
139
+ # @ref http://oauth.net/core/1.0/#rfc.section.9.1.1
140
+ # @ref http://oauth.net/core/1.0/#9.2.1
141
+ # @ref http://oauth.net/core/1.0/#rfc.section.A.5.1
142
+ def query_string
143
+ pairs = []
144
+ @params.sort.each { | key, val |
145
+ pairs.push( "#{ percent_encode( key ) }=#{ percent_encode( val.to_s ) }" )
146
+ }
147
+ pairs.join '&'
148
+ end
149
+
150
+ def timestamp
151
+ Time.now.to_i.to_s
152
+ end
153
+
154
+ # organize params & create signature
155
+ def sign( parsed_url )
156
+
157
+ @params = {
158
+ 'oauth_consumer_key' => @consumer_key,
159
+ 'oauth_nonce' => nonce,
160
+ 'oauth_signature_method' => @sig_method,
161
+ 'oauth_timestamp' => timestamp,
162
+ 'oauth_version' => @oauth_version
163
+ }
164
+
165
+ # if url has query, merge key/values into params obj overwriting defaults
166
+ if parsed_url.query
167
+ CGI.parse( parsed_url.query ).each do |k,v|
168
+ if v.is_a?(Array) && v.count == 1
169
+ @params[k] = v.first
170
+ else
171
+ @params[k] = v
172
+ end
173
+ end
174
+ end
175
+
176
+ # @ref http://oauth.net/core/1.0/#rfc.section.9.1.2
177
+ @req_url = parsed_url.scheme + '://' + parsed_url.host + parsed_url.path
178
+
179
+ # create base str. make it an object attr for ez debugging
180
+ # ref http://oauth.net/core/1.0/#anchor14
181
+ @base_str = [
182
+ @req_method,
183
+ percent_encode( req_url ),
184
+
185
+ # normalization is just x-www-form-urlencoded
186
+ percent_encode( query_string )
187
+
188
+ ].join( '&' )
189
+
190
+ # add signature
191
+ @params[ 'oauth_signature' ] = signature
192
+
193
+ return self
194
+ end
195
+ end