sutto-oauth 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data/History.txt +114 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +86 -0
  4. data/README.rdoc +71 -0
  5. data/Rakefile +38 -0
  6. data/TODO +31 -0
  7. data/bin/oauth +5 -0
  8. data/examples/yql.rb +44 -0
  9. data/lib/oauth.rb +4 -0
  10. data/lib/oauth/cli.rb +378 -0
  11. data/lib/oauth/client.rb +4 -0
  12. data/lib/oauth/client/action_controller_request.rb +54 -0
  13. data/lib/oauth/client/helper.rb +85 -0
  14. data/lib/oauth/client/net_http.rb +106 -0
  15. data/lib/oauth/consumer.rb +370 -0
  16. data/lib/oauth/errors.rb +3 -0
  17. data/lib/oauth/errors/error.rb +4 -0
  18. data/lib/oauth/errors/problem.rb +14 -0
  19. data/lib/oauth/errors/unauthorized.rb +12 -0
  20. data/lib/oauth/helper.rb +78 -0
  21. data/lib/oauth/oauth.rb +11 -0
  22. data/lib/oauth/oauth_test_helper.rb +25 -0
  23. data/lib/oauth/request_proxy.rb +24 -0
  24. data/lib/oauth/request_proxy/action_controller_request.rb +61 -0
  25. data/lib/oauth/request_proxy/base.rb +166 -0
  26. data/lib/oauth/request_proxy/jabber_request.rb +41 -0
  27. data/lib/oauth/request_proxy/mock_request.rb +44 -0
  28. data/lib/oauth/request_proxy/net_http.rb +65 -0
  29. data/lib/oauth/request_proxy/rack_request.rb +40 -0
  30. data/lib/oauth/server.rb +66 -0
  31. data/lib/oauth/signature.rb +40 -0
  32. data/lib/oauth/signature/base.rb +91 -0
  33. data/lib/oauth/signature/hmac/base.rb +12 -0
  34. data/lib/oauth/signature/hmac/md5.rb +9 -0
  35. data/lib/oauth/signature/hmac/rmd160.rb +9 -0
  36. data/lib/oauth/signature/hmac/sha1.rb +9 -0
  37. data/lib/oauth/signature/hmac/sha2.rb +9 -0
  38. data/lib/oauth/signature/md5.rb +13 -0
  39. data/lib/oauth/signature/plaintext.rb +23 -0
  40. data/lib/oauth/signature/rsa/sha1.rb +45 -0
  41. data/lib/oauth/signature/sha1.rb +13 -0
  42. data/lib/oauth/token.rb +7 -0
  43. data/lib/oauth/tokens/access_token.rb +68 -0
  44. data/lib/oauth/tokens/consumer_token.rb +33 -0
  45. data/lib/oauth/tokens/request_token.rb +32 -0
  46. data/lib/oauth/tokens/server_token.rb +9 -0
  47. data/lib/oauth/tokens/token.rb +17 -0
  48. data/lib/oauth/version.rb +3 -0
  49. data/oauth.gemspec +49 -0
  50. data/script/destroy +14 -0
  51. data/script/generate +14 -0
  52. data/script/txt2html +74 -0
  53. data/setup.rb +1585 -0
  54. data/tasks/deployment.rake +34 -0
  55. data/tasks/environment.rake +7 -0
  56. data/tasks/website.rake +17 -0
  57. data/test/cases/oauth_case.rb +19 -0
  58. data/test/cases/spec/1_0-final/test_construct_request_url.rb +62 -0
  59. data/test/cases/spec/1_0-final/test_normalize_request_parameters.rb +88 -0
  60. data/test/cases/spec/1_0-final/test_parameter_encodings.rb +86 -0
  61. data/test/cases/spec/1_0-final/test_signature_base_strings.rb +77 -0
  62. data/test/keys/rsa.cert +11 -0
  63. data/test/keys/rsa.pem +16 -0
  64. data/test/test_access_token.rb +26 -0
  65. data/test/test_action_controller_request_proxy.rb +132 -0
  66. data/test/test_consumer.rb +159 -0
  67. data/test/test_helper.rb +14 -0
  68. data/test/test_hmac_sha1.rb +20 -0
  69. data/test/test_net_http_client.rb +221 -0
  70. data/test/test_net_http_request_proxy.rb +72 -0
  71. data/test/test_oauth_helper.rb +49 -0
  72. data/test/test_rack_request_proxy.rb +40 -0
  73. data/test/test_request_token.rb +51 -0
  74. data/test/test_rsa_sha1.rb +59 -0
  75. data/test/test_server.rb +40 -0
  76. data/test/test_signature.rb +19 -0
  77. data/test/test_signature_base.rb +32 -0
  78. data/test/test_signature_plain_text.rb +31 -0
  79. data/test/test_token.rb +14 -0
  80. data/website/index.html +87 -0
  81. data/website/index.txt +73 -0
  82. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  83. data/website/stylesheets/screen.css +138 -0
  84. data/website/template.rhtml +48 -0
  85. metadata +217 -0
@@ -0,0 +1,4 @@
1
+ module OAuth
2
+ module Client
3
+ end
4
+ end
@@ -0,0 +1,54 @@
1
+ require 'oauth/client/helper'
2
+ require 'oauth/request_proxy/action_controller_request'
3
+ require 'action_controller/test_process'
4
+
5
+ module ActionController
6
+ class Base
7
+ def process_with_oauth(request, response=nil)
8
+ request.apply_oauth! if request.respond_to?(:apply_oauth!)
9
+ process_without_oauth(request, response)
10
+ end
11
+
12
+ alias_method_chain :process, :oauth
13
+ end
14
+
15
+ class TestRequest
16
+ def self.use_oauth=(bool)
17
+ @use_oauth = bool
18
+ end
19
+
20
+ def self.use_oauth?
21
+ @use_oauth
22
+ end
23
+
24
+ def configure_oauth(consumer = nil, token = nil, options = {})
25
+ @oauth_options = { :consumer => consumer,
26
+ :token => token,
27
+ :scheme => 'header',
28
+ :signature_method => nil,
29
+ :nonce => nil,
30
+ :timestamp => nil }.merge(options)
31
+ end
32
+
33
+ def apply_oauth!
34
+ return unless ActionController::TestRequest.use_oauth? && @oauth_options
35
+
36
+ @oauth_helper = OAuth::Client::Helper.new(self, @oauth_options.merge(:request_uri => request_uri))
37
+ @oauth_helper.amend_user_agent_header(env)
38
+
39
+ self.send("set_oauth_#{@oauth_options[:scheme]}")
40
+ end
41
+
42
+ def set_oauth_header
43
+ env['Authorization'] = @oauth_helper.header
44
+ end
45
+
46
+ def set_oauth_parameters
47
+ @query_parameters = @oauth_helper.parameters_with_oauth
48
+ @query_parameters.merge!(:oauth_signature => @oauth_helper.signature)
49
+ end
50
+
51
+ def set_oauth_query_string
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,85 @@
1
+ require 'oauth/client'
2
+ require 'oauth/consumer'
3
+ require 'oauth/helper'
4
+ require 'oauth/token'
5
+ require 'oauth/version'
6
+ require 'oauth/signature/hmac/sha1'
7
+
8
+ module OAuth::Client
9
+ class Helper
10
+ include OAuth::Helper
11
+
12
+ def initialize(request, options = {})
13
+ @request = request
14
+ @options = options
15
+ @options[:signature_method] ||= 'HMAC-SHA1'
16
+ end
17
+
18
+ def options
19
+ @options
20
+ end
21
+
22
+ def nonce
23
+ options[:nonce] ||= generate_key
24
+ end
25
+
26
+ def timestamp
27
+ options[:timestamp] ||= generate_timestamp
28
+ end
29
+
30
+ def oauth_parameters
31
+ {
32
+ 'oauth_callback' => options[:oauth_callback],
33
+ 'oauth_consumer_key' => options[:consumer].key,
34
+ 'oauth_token' => options[:token] ? options[:token].token : '',
35
+ 'oauth_signature_method' => options[:signature_method],
36
+ 'oauth_timestamp' => timestamp,
37
+ 'oauth_nonce' => nonce,
38
+ 'oauth_verifier' => options[:oauth_verifier],
39
+ 'oauth_version' => (options[:oauth_version] || '1.0')
40
+ }.reject { |k,v| v.to_s == "" }
41
+ end
42
+
43
+ def signature(extra_options = {})
44
+ OAuth::Signature.sign(@request, { :uri => options[:request_uri],
45
+ :consumer => options[:consumer],
46
+ :token => options[:token],
47
+ :unsigned_parameters => options[:unsigned_parameters]
48
+ }.merge(extra_options) )
49
+ end
50
+
51
+ def signature_base_string(extra_options = {})
52
+ OAuth::Signature.signature_base_string(@request, { :uri => options[:request_uri],
53
+ :consumer => options[:consumer],
54
+ :token => options[:token],
55
+ :parameters => oauth_parameters}.merge(extra_options) )
56
+ end
57
+
58
+ def amend_user_agent_header(headers)
59
+ @oauth_ua_string ||= "OAuth gem v#{OAuth::VERSION}"
60
+ if headers['User-Agent']
61
+ headers['User-Agent'] += " (#{@oauth_ua_string})"
62
+ else
63
+ headers['User-Agent'] = @oauth_ua_string
64
+ end
65
+ end
66
+
67
+ def header
68
+ parameters = oauth_parameters
69
+ parameters.merge!('oauth_signature' => signature(options.merge(:parameters => parameters)))
70
+
71
+ header_params_str = parameters.map { |k,v| "#{k}=\"#{escape(v)}\"" }.join(', ')
72
+
73
+ realm = "realm=\"#{options[:realm]}\", " if options[:realm]
74
+ "OAuth #{realm}#{header_params_str}"
75
+ end
76
+
77
+ def parameters
78
+ OAuth::RequestProxy.proxy(@request).parameters
79
+ end
80
+
81
+ def parameters_with_oauth
82
+ oauth_parameters.merge(parameters)
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,106 @@
1
+ require 'oauth/helper'
2
+ require 'oauth/client/helper'
3
+ require 'oauth/request_proxy/net_http'
4
+
5
+ class Net::HTTPRequest
6
+ include OAuth::Helper
7
+
8
+ attr_reader :oauth_helper
9
+
10
+ # Add the OAuth information to an HTTP request. Depending on the <tt>options[:scheme]</tt> setting
11
+ # this may add a header, additional query string parameters, or additional POST body parameters.
12
+ # The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
13
+ # header.
14
+ #
15
+ # * http - Configured Net::HTTP instance
16
+ # * consumer - OAuth::Consumer instance
17
+ # * token - OAuth::Token instance
18
+ # * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
19
+ # +signature_method+, +nonce+, +timestamp+)
20
+ #
21
+ # This method also modifies the <tt>User-Agent</tt> header to add the OAuth gem version.
22
+ #
23
+ # See Also: {OAuth core spec version 1.0, section 5.4.1}[http://oauth.net/core/1.0#rfc.section.5.4.1]
24
+ def oauth!(http, consumer = nil, token = nil, options = {})
25
+ options = { :request_uri => oauth_full_request_uri(http),
26
+ :consumer => consumer,
27
+ :token => token,
28
+ :scheme => 'header',
29
+ :signature_method => nil,
30
+ :nonce => nil,
31
+ :timestamp => nil }.merge(options)
32
+
33
+ @oauth_helper = OAuth::Client::Helper.new(self, options)
34
+ @oauth_helper.amend_user_agent_header(self)
35
+ self.send("set_oauth_#{options[:scheme]}")
36
+ end
37
+
38
+ # Create a string suitable for signing for an HTTP request. This process involves parameter
39
+ # normalization as specified in the OAuth specification. The exact normalization also depends
40
+ # on the <tt>options[:scheme]</tt> being used so this must match what will be used for the request
41
+ # itself. The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
42
+ # header.
43
+ #
44
+ # * http - Configured Net::HTTP instance
45
+ # * consumer - OAuth::Consumer instance
46
+ # * token - OAuth::Token instance
47
+ # * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
48
+ # +signature_method+, +nonce+, +timestamp+)
49
+ #
50
+ # See Also: {OAuth core spec version 1.0, section 9.1.1}[http://oauth.net/core/1.0#rfc.section.9.1.1]
51
+ def signature_base_string(http, consumer = nil, token = nil, options = {})
52
+ options = { :request_uri => oauth_full_request_uri(http),
53
+ :consumer => consumer,
54
+ :token => token,
55
+ :scheme => 'header',
56
+ :signature_method => nil,
57
+ :nonce => nil,
58
+ :timestamp => nil }.merge(options)
59
+
60
+ OAuth::Client::Helper.new(self, options).signature_base_string
61
+ end
62
+
63
+ private
64
+
65
+ def oauth_full_request_uri(http)
66
+ uri = URI.parse(self.path)
67
+ uri.host = http.address
68
+ uri.port = http.port
69
+
70
+ if http.respond_to?(:use_ssl?) && http.use_ssl?
71
+ uri.scheme = "https"
72
+ else
73
+ uri.scheme = "http"
74
+ end
75
+
76
+ uri.to_s
77
+ end
78
+
79
+ def set_oauth_header
80
+ self['Authorization'] = @oauth_helper.header
81
+ end
82
+
83
+ # FIXME: if you're using a POST body and query string parameters, using this
84
+ # method will convert those parameters on the query string into parameters in
85
+ # the body. this is broken, and should be fixed.
86
+ def set_oauth_body
87
+ self.set_form_data(@oauth_helper.parameters_with_oauth)
88
+ params_with_sig = @oauth_helper.parameters.merge(:oauth_signature => @oauth_helper.signature)
89
+ self.set_form_data(params_with_sig)
90
+ end
91
+
92
+ def set_oauth_query_string
93
+ oauth_params_str = @oauth_helper.oauth_parameters.map { |k,v| [escape(k), escape(v)] * "=" }.join("&")
94
+
95
+ uri = URI.parse(path)
96
+ if uri.query.to_s == ""
97
+ uri.query = oauth_params_str
98
+ else
99
+ uri.query = uri.query + "&" + oauth_params_str
100
+ end
101
+
102
+ @path = uri.to_s
103
+
104
+ @path << "&oauth_signature=#{escape(oauth_helper.signature)}"
105
+ end
106
+ end
@@ -0,0 +1,370 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'oauth/oauth'
4
+ require 'oauth/client/net_http'
5
+ require 'oauth/errors'
6
+
7
+ module OAuth
8
+ class Consumer
9
+ # determine the certificate authority path to verify SSL certs
10
+ CA_FILES = %w(/etc/ssl/certs/ca-certificates.crt /usr/share/curl/curl-ca-bundle.crt)
11
+ CA_FILES.each do |ca_file|
12
+ if File.exists?(ca_file)
13
+ CA_FILE = ca_file
14
+ break
15
+ end
16
+ end
17
+ CA_FILE = nil unless defined?(CA_FILE)
18
+
19
+ @@default_options = {
20
+ # Signature method used by server. Defaults to HMAC-SHA1
21
+ :signature_method => 'HMAC-SHA1',
22
+
23
+ # default paths on site. These are the same as the defaults set up by the generators
24
+ :request_token_path => '/oauth/request_token',
25
+ :authorize_path => '/oauth/authorize',
26
+ :access_token_path => '/oauth/access_token',
27
+
28
+ :proxy => nil,
29
+ # How do we send the oauth values to the server see
30
+ # http://oauth.net/core/1.0/#consumer_req_param for more info
31
+ #
32
+ # Possible values:
33
+ #
34
+ # :header - via the Authorize header (Default) ( option 1. in spec)
35
+ # :body - url form encoded in body of POST request ( option 2. in spec)
36
+ # :query_string - via the query part of the url ( option 3. in spec)
37
+ :scheme => :header,
38
+
39
+ # Default http method used for OAuth Token Requests (defaults to :post)
40
+ :http_method => :post,
41
+
42
+ # Add a custom ca_file for consumer
43
+ # :ca_file => '/etc/certs.pem'
44
+
45
+ :oauth_version => "1.0"
46
+ }
47
+
48
+ attr_accessor :options, :key, :secret
49
+ attr_writer :site, :http
50
+
51
+ # Create a new consumer instance by passing it a configuration hash:
52
+ #
53
+ # @consumer = OAuth::Consumer.new(key, secret, {
54
+ # :site => "http://term.ie",
55
+ # :scheme => :header,
56
+ # :http_method => :post,
57
+ # :request_token_path => "/oauth/example/request_token.php",
58
+ # :access_token_path => "/oauth/example/access_token.php",
59
+ # :authorize_path => "/oauth/example/authorize.php"
60
+ # })
61
+ #
62
+ # Start the process by requesting a token
63
+ #
64
+ # @request_token = @consumer.get_request_token
65
+ # session[:request_token] = @request_token
66
+ # redirect_to @request_token.authorize_url
67
+ #
68
+ # When user returns create an access_token
69
+ #
70
+ # @access_token = @request_token.get_access_token
71
+ # @photos=@access_token.get('/photos.xml')
72
+ #
73
+ def initialize(consumer_key, consumer_secret, options = {})
74
+ @key = consumer_key
75
+ @secret = consumer_secret
76
+
77
+ # ensure that keys are symbols
78
+ @options = @@default_options.merge(options.inject({}) { |options, (key, value)|
79
+ options[key.to_sym] = value
80
+ options
81
+ })
82
+ end
83
+
84
+ # The default http method
85
+ def http_method
86
+ @http_method ||= @options[:http_method] || :post
87
+ end
88
+
89
+ # The HTTP object for the site. The HTTP Object is what you get when you do Net::HTTP.new
90
+ def http
91
+ @http ||= create_http
92
+ end
93
+
94
+ # Contains the root URI for this site
95
+ def uri(custom_uri = nil)
96
+ if custom_uri
97
+ @uri = custom_uri
98
+ @http = create_http # yike, oh well. less intrusive this way
99
+ else # if no custom passed, we use existing, which, if unset, is set to site uri
100
+ @uri ||= URI.parse(site)
101
+ end
102
+ end
103
+
104
+ def get_access_token(request_token, request_options = {}, *arguments, &block)
105
+ response = token_request(http_method, (access_token_url? ? access_token_url : access_token_path), request_token, request_options, *arguments, &block)
106
+ OAuth::AccessToken.from_hash(self, response)
107
+ end
108
+
109
+ # Makes a request to the service for a new OAuth::RequestToken
110
+ #
111
+ # @request_token = @consumer.get_request_token
112
+ #
113
+ # To include OAuth parameters:
114
+ #
115
+ # @request_token = @consumer.get_request_token \
116
+ # :oauth_callback => "http://example.com/cb"
117
+ #
118
+ # To include application-specific parameters:
119
+ #
120
+ # @request_token = @consumer.get_request_token({}, :foo => "bar")
121
+ #
122
+ # TODO oauth_callback should be a mandatory parameter
123
+ def get_request_token(request_options = {}, *arguments, &block)
124
+ # if oauth_callback wasn't provided, it is assumed that oauth_verifiers
125
+ # will be exchanged out of band
126
+ request_options[:oauth_callback] ||= OAuth::OUT_OF_BAND unless request_options[:exclude_callback]
127
+
128
+ if block_given?
129
+ response = token_request(http_method,
130
+ (request_token_url? ? request_token_url : request_token_path),
131
+ nil,
132
+ request_options,
133
+ *arguments, &block)
134
+ else
135
+ response = token_request(http_method, (request_token_url? ? request_token_url : request_token_path), nil, request_options, *arguments)
136
+ end
137
+ OAuth::RequestToken.from_hash(self, response)
138
+ end
139
+
140
+ # Creates, signs and performs an http request.
141
+ # It's recommended to use the OAuth::Token classes to set this up correctly.
142
+ # request_options take precedence over consumer-wide options when signing
143
+ # a request.
144
+ # arguments are POST and PUT bodies (a Hash, string-encoded parameters, or
145
+ # absent), followed by additional HTTP headers.
146
+ #
147
+ # @consumer.request(:get, '/people', @token, { :scheme => :query_string })
148
+ # @consumer.request(:post, '/people', @token, {}, @person.to_xml, { 'Content-Type' => 'application/xml' })
149
+ #
150
+ def request(http_method, path, token = nil, request_options = {}, *arguments)
151
+ if path !~ /^\//
152
+ @http = create_http(path)
153
+ _uri = URI.parse(path)
154
+ path = "#{_uri.path}#{_uri.query ? "?#{_uri.query}" : ""}"
155
+ end
156
+
157
+ # override the request with your own, this is useful for file uploads which Net::HTTP does not do
158
+ req = create_signed_request(http_method, path, token, request_options, *arguments)
159
+ return nil if block_given? and yield(req) == :done
160
+ rsp = http.request(req)
161
+
162
+ # check for an error reported by the Problem Reporting extension
163
+ # (http://wiki.oauth.net/ProblemReporting)
164
+ # note: a 200 may actually be an error; check for an oauth_problem key to be sure
165
+ if !(headers = rsp.to_hash["www-authenticate"]).nil? &&
166
+ (h = headers.select { |h| h =~ /^OAuth / }).any? &&
167
+ h.first =~ /oauth_problem/
168
+
169
+ # puts "Header: #{h.first}"
170
+
171
+ # TODO doesn't handle broken responses from api.login.yahoo.com
172
+ # remove debug code when done
173
+ params = OAuth::Helper.parse_header(h.first)
174
+
175
+ # puts "Params: #{params.inspect}"
176
+ # puts "Body: #{rsp.body}"
177
+
178
+ raise OAuth::Problem.new(params.delete("oauth_problem"), rsp, params)
179
+ end
180
+
181
+ rsp
182
+ end
183
+
184
+ # Creates and signs an http request.
185
+ # It's recommended to use the Token classes to set this up correctly
186
+ def create_signed_request(http_method, path, token = nil, request_options = {}, *arguments)
187
+ request = create_http_request(http_method, path, *arguments)
188
+ sign!(request, token, request_options)
189
+ request
190
+ end
191
+
192
+ # Creates a request and parses the result as url_encoded. This is used internally for the RequestToken and AccessToken requests.
193
+ def token_request(http_method, path, token = nil, request_options = {}, *arguments)
194
+ response = request(http_method, path, token, request_options, *arguments)
195
+
196
+ case response.code.to_i
197
+
198
+ when (200..299)
199
+ if block_given?
200
+ yield response.body
201
+ else
202
+ # symbolize keys
203
+ # TODO this could be considered unexpected behavior; symbols or not?
204
+ # TODO this also drops subsequent values from multi-valued keys
205
+ CGI.parse(response.body).inject({}) do |h,(k,v)|
206
+ h[k.strip.to_sym] = v.first
207
+ h[k.strip] = v.first
208
+ h
209
+ end
210
+ end
211
+ when (300..399)
212
+ # this is a redirect
213
+ response.error!
214
+ when (400..499)
215
+ raise OAuth::Unauthorized, response
216
+ else
217
+ response.error!
218
+ end
219
+ end
220
+
221
+ # Sign the Request object. Use this if you have an externally generated http request object you want to sign.
222
+ def sign!(request, token = nil, request_options = {})
223
+ request.oauth!(http, self, token, options.merge(request_options))
224
+ end
225
+
226
+ # Return the signature_base_string
227
+ def signature_base_string(request, token = nil, request_options = {})
228
+ request.signature_base_string(http, self, token, options.merge(request_options))
229
+ end
230
+
231
+ def site
232
+ @options[:site].to_s
233
+ end
234
+
235
+ def scheme
236
+ @options[:scheme]
237
+ end
238
+
239
+ def request_token_path
240
+ @options[:request_token_path]
241
+ end
242
+
243
+ def authorize_path
244
+ @options[:authorize_path]
245
+ end
246
+
247
+ def access_token_path
248
+ @options[:access_token_path]
249
+ end
250
+
251
+ # TODO this is ugly, rewrite
252
+ def request_token_url
253
+ @options[:request_token_url] || site + request_token_path
254
+ end
255
+
256
+ def request_token_url?
257
+ @options.has_key?(:request_token_url)
258
+ end
259
+
260
+ def authorize_url
261
+ @options[:authorize_url] || site + authorize_path
262
+ end
263
+
264
+ def authorize_url?
265
+ @options.has_key?(:authorize_url)
266
+ end
267
+
268
+ def access_token_url
269
+ @options[:access_token_url] || site + access_token_path
270
+ end
271
+
272
+ def access_token_url?
273
+ @options.has_key?(:access_token_url)
274
+ end
275
+
276
+ def proxy
277
+ @options[:proxy]
278
+ end
279
+
280
+ protected
281
+
282
+ # Instantiates the http object
283
+ def create_http(_url = nil)
284
+ if _url.nil? || _url[0] =~ /^\//
285
+ our_uri = URI.parse(site)
286
+ else
287
+ our_uri = URI.parse(_url)
288
+ end
289
+
290
+ if proxy.nil?
291
+ http_object = Net::HTTP.new(our_uri.host, our_uri.port)
292
+ else
293
+ proxy_uri = proxy.is_a?(URI) ? proxy : URI.parse(proxy)
294
+ http_object = Net::HTTP.new(our_uri.host, our_uri.port, proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
295
+ end
296
+
297
+ http_object.use_ssl = (our_uri.scheme == 'https')
298
+
299
+ if @options[:ca_file] || CA_FILE
300
+ http_object.ca_file = @options[:ca_file] || CA_FILE
301
+ http_object.verify_mode = OpenSSL::SSL::VERIFY_PEER
302
+ http_object.verify_depth = 5
303
+ else
304
+ http_object.verify_mode = OpenSSL::SSL::VERIFY_NONE
305
+ end
306
+
307
+ http_object
308
+ end
309
+
310
+ # create the http request object for a given http_method and path
311
+ def create_http_request(http_method, path, *arguments)
312
+ http_method = http_method.to_sym
313
+
314
+ if [:post, :put].include?(http_method)
315
+ data = arguments.shift
316
+ data.reject! { |k,v| v.nil? } if data.is_a?(Hash)
317
+ end
318
+
319
+ headers = arguments.first.is_a?(Hash) ? arguments.shift : {}
320
+
321
+ case http_method
322
+ when :post
323
+ request = Net::HTTP::Post.new(path,headers)
324
+ request["Content-Length"] = 0 # Default to 0
325
+ when :put
326
+ request = Net::HTTP::Put.new(path,headers)
327
+ request["Content-Length"] = 0 # Default to 0
328
+ when :get
329
+ request = Net::HTTP::Get.new(path,headers)
330
+ when :delete
331
+ request = Net::HTTP::Delete.new(path,headers)
332
+ when :head
333
+ request = Net::HTTP::Head.new(path,headers)
334
+ else
335
+ raise ArgumentError, "Don't know how to handle http_method: :#{http_method.to_s}"
336
+ end
337
+
338
+ if data.is_a?(Hash)
339
+ request.set_form_data(data)
340
+ elsif data
341
+ if data.respond_to?(:read)
342
+ request.body_stream = data
343
+ if data.respond_to?(:length)
344
+ request["Content-Length"] = data.length
345
+ elsif data.respond_to?(:stat) && data.stat.respond_to?(:size)
346
+ request["Content-Length"] = data.stat.size
347
+ else
348
+ raise ArgumentError, "Don't know how to send a body_stream that doesn't respond to .length or .stat.size"
349
+ end
350
+ else
351
+ request.body = data.to_s
352
+ request["Content-Length"] = request.body.length
353
+ end
354
+ end
355
+
356
+ request
357
+ end
358
+
359
+ def marshal_dump(*args)
360
+ {:key => @key,
361
+ :secret => @secret,
362
+ :options => @options}
363
+ end
364
+
365
+ def marshal_load(data)
366
+ initialize(data[:key], data[:secret], data[:options])
367
+ end
368
+
369
+ end
370
+ end