oauth 0.3.4 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of oauth might be problematic. Click here for more details.

@@ -1,3 +1,13 @@
1
+ == 0.3.5 2009-06-03
2
+
3
+ * `query` CLI command to access protected resources (Seth)
4
+ * Added -H, -Q CLI options for specifying the authorization scheme (Seth)
5
+ * Added -O CLI option for specifying a file containing options (Seth)
6
+ * Support streamable body contents for large request bodies (Seth Cousins)
7
+ * Support for OAuth 1.0a (Seth)
8
+ * Added proxy support to OAuth::Consumer (Marshall Huss)
9
+ * Added --scope CLI option for Google's 'scope' parameter (Seth)
10
+
1
11
  == 0.3.4 2009-05-06
2
12
 
3
13
  * OAuth::Client::Helper uses OAuth::VERSION (chadisfaction)
@@ -39,6 +39,6 @@ consumer = OAuth::Consumer.new \
39
39
 
40
40
  access_token = OAuth::AccessToken.new(consumer)
41
41
 
42
- response = access_token.request(:get, url = "/v1/yql?q=#{OAuth::Helper.escape(query)}&format=json")
42
+ response = access_token.request(:get, "/v1/yql?q=#{OAuth::Helper.escape(query)}&format=json")
43
43
  rsp = JSON.parse(response.body)
44
44
  pp rsp
@@ -6,7 +6,9 @@ module OAuth
6
6
  SUPPORTED_COMMANDS = {
7
7
  "authorize" => "Obtain an access token and secret for a user",
8
8
  "debug" => "Verbosely generate an OAuth signature",
9
- "sign" => "Generate an OAuth signature"
9
+ "query" => "Query a protected resource",
10
+ "sign" => "Generate an OAuth signature",
11
+ "version" => "Display the current version of the library"
10
12
  }
11
13
 
12
14
  attr_reader :command
@@ -41,38 +43,66 @@ module OAuth
41
43
  case command
42
44
  # TODO move command logic elsewhere
43
45
  when "authorize"
44
- # Y! token authority requires realm=yahoo.com when headers are in use
45
- # TODO remove :scheme when that's been fixed
46
- # TODO determine endpoints w/ X-RDS-Simple
47
- consumer = OAuth::Consumer.new \
48
- options[:oauth_consumer_key],
49
- options[:oauth_consumer_secret],
50
- :access_token_url => options[:access_token_url],
51
- :authorize_url => options[:authorize_url],
52
- :request_token_url => options[:request_token_url],
53
- :scheme => :query_string
46
+ begin
47
+ consumer = OAuth::Consumer.new \
48
+ options[:oauth_consumer_key],
49
+ options[:oauth_consumer_secret],
50
+ :access_token_url => options[:access_token_url],
51
+ :authorize_url => options[:authorize_url],
52
+ :request_token_url => options[:request_token_url],
53
+ :scheme => options[:scheme]
54
+
55
+ # parameters for OAuth 1.0a
56
+ oauth_verifier = nil
57
+
58
+ # get a request token
59
+ request_token = consumer.get_request_token({ :oauth_callback => options[:oauth_callback] }, { :scope => options[:scope] })
60
+
61
+ if request_token.callback_confirmed?
62
+ stdout.puts "Server appears to support OAuth 1.0a; enabling support."
63
+ options[:version] = "1.0a"
64
+ end
54
65
 
55
- # get a request token
56
- request_token = consumer.get_request_token
66
+ stdout.puts "Please visit this url to authorize:"
67
+ stdout.puts request_token.authorize_url
57
68
 
58
- stdout.puts "Please visit this url to authorize:"
59
- stdout.puts request_token.authorize_url
69
+ if options[:version] == "1.0a"
70
+ stdout.puts "Please enter the verification code provided by the SP (oauth_verifier):"
71
+ oauth_verifier = stdin.gets.chomp
72
+ else
73
+ stdout.puts "Press return to continue..."
74
+ stdin.gets
75
+ end
60
76
 
61
- stdout.puts "Press return to continue..."
62
- stdin.gets
77
+ begin
78
+ # get an access token
79
+ access_token = request_token.get_access_token(:oauth_verifier => oauth_verifier)
63
80
 
64
- begin
65
- # get an access token
66
- access_token = request_token.get_access_token
67
-
68
- stdout.puts "Response:"
69
- access_token.params.each do |k,v|
70
- stdout.puts " #{k}: #{v}"
81
+ stdout.puts "Response:"
82
+ access_token.params.each do |k,v|
83
+ stdout.puts " #{k}: #{v}" unless k.is_a?(Symbol)
84
+ end
85
+ rescue OAuth::Unauthorized => e
86
+ stderr.puts "A problem occurred while attempting to obtain an access token:"
87
+ stderr.puts e
88
+ stderr.puts e.request.body
71
89
  end
72
90
  rescue OAuth::Unauthorized => e
73
- stderr.puts "A problem occurred while attempting to obtain an access token:"
91
+ stderr.puts "A problem occurred while attempting to authorize:"
74
92
  stderr.puts e
93
+ stderr.puts e.request.body
75
94
  end
95
+ when "query"
96
+ consumer = OAuth::Consumer.new \
97
+ options[:oauth_consumer_key],
98
+ options[:oauth_consumer_secret],
99
+ :scheme => options[:scheme]
100
+
101
+ access_token = OAuth::AccessToken.new(consumer, options[:oauth_token], options[:oauth_token_secret])
102
+
103
+ response = access_token.request(options[:method].downcase.to_sym, options[:uri])
104
+ puts "#{response.code} #{response.message}"
105
+ puts response.body
76
106
  when "sign"
77
107
  parameters = prepare_parameters
78
108
 
@@ -134,6 +164,8 @@ module OAuth
134
164
  else
135
165
  stdout.puts request.oauth_signature
136
166
  end
167
+ when "version"
168
+ puts "OAuth for Ruby #{OAuth::VERSION}"
137
169
  end
138
170
  else
139
171
  usage
@@ -147,7 +179,9 @@ module OAuth
147
179
  parse_options(arguments[0..-1])
148
180
  end
149
181
 
150
- def option_parser
182
+ def option_parser(arguments = "")
183
+ # TODO add realm parameter
184
+ # TODO add user-agent parameter
151
185
  option_parser = OptionParser.new do |opts|
152
186
  opts.banner = "Usage: #{$0} [options] <command>"
153
187
 
@@ -157,6 +191,8 @@ module OAuth
157
191
  options[:oauth_timestamp] = OAuth::Helper.generate_timestamp
158
192
  options[:oauth_version] = "1.0"
159
193
  options[:params] = []
194
+ options[:scheme] = :header
195
+ options[:version] = "1.0"
160
196
 
161
197
  ## Common Options
162
198
 
@@ -168,7 +204,21 @@ module OAuth
168
204
  options[:oauth_consumer_secret] = v
169
205
  end
170
206
 
171
- ## Options for signing
207
+ opts.on("-H", "--header", "Use the 'Authorization' header for OAuth parameters (default).") do
208
+ options[:scheme] = :header
209
+ end
210
+
211
+ opts.on("-Q", "--query-string", "Use the query string for OAuth parameters.") do
212
+ options[:scheme] = :query_string
213
+ end
214
+
215
+ opts.on("-O", "--options FILE", "Read options from a file") do |v|
216
+ arguments.unshift(*open(v).readlines.map { |l| l.chomp.split(" ") }.flatten)
217
+ end
218
+
219
+ ## Options for signing and making requests
220
+
221
+ opts.separator("\n options for signing and querying")
172
222
 
173
223
  opts.on("--method METHOD", "Specifies the method (e.g. GET) to use when signing.") do |v|
174
224
  options[:method] = v
@@ -206,8 +256,12 @@ module OAuth
206
256
  options[:uri] = v
207
257
  end
208
258
 
209
- opts.on("--version VERSION", "Specifies the OAuth version to use.") do |v|
210
- options[:oauth_version] = v
259
+ opts.on(:OPTIONAL, "--version VERSION", "Specifies the OAuth version to use.") do |v|
260
+ if v
261
+ options[:oauth_version] = v
262
+ else
263
+ @command = "version"
264
+ end
211
265
  end
212
266
 
213
267
  opts.on("--no-version", "Omit oauth_version.") do
@@ -225,6 +279,8 @@ module OAuth
225
279
 
226
280
  ## Options for authorization
227
281
 
282
+ opts.separator("\n options for authorization")
283
+
228
284
  opts.on("--access-token-url URL", "Specifies the access token URL.") do |v|
229
285
  options[:access_token_url] = v
230
286
  end
@@ -233,14 +289,22 @@ module OAuth
233
289
  options[:authorize_url] = v
234
290
  end
235
291
 
292
+ opts.on("--callback-url URL", "Specifies a callback URL.") do |v|
293
+ options[:oauth_callback] = v
294
+ end
295
+
236
296
  opts.on("--request-token-url URL", "Specifies the request token URL.") do |v|
237
297
  options[:request_token_url] = v
238
298
  end
299
+
300
+ opts.on("--scope SCOPE", "Specifies the scope (Google-specific).") do |v|
301
+ options[:scope] = v
302
+ end
239
303
  end
240
304
  end
241
305
 
242
306
  def parse_options(arguments)
243
- option_parser.parse!(arguments)
307
+ option_parser(arguments).parse!(arguments)
244
308
  end
245
309
 
246
310
  def prepare_parameters
@@ -274,6 +338,8 @@ module OAuth
274
338
  options[:oauth_consumer_key] && options[:oauth_consumer_secret] &&
275
339
  options[:access_token_url] && options[:authorize_url] &&
276
340
  options[:request_token_url]
341
+ when "version"
342
+ true
277
343
  else
278
344
  options[:oauth_consumer_key] && options[:oauth_consumer_secret] &&
279
345
  options[:method] && options[:uri]
@@ -29,11 +29,13 @@ module OAuth::Client
29
29
 
30
30
  def oauth_parameters
31
31
  {
32
+ 'oauth_callback' => options[:oauth_callback],
32
33
  'oauth_consumer_key' => options[:consumer].key,
33
34
  'oauth_token' => options[:token] ? options[:token].token : '',
34
35
  'oauth_signature_method' => options[:signature_method],
35
36
  'oauth_timestamp' => timestamp,
36
37
  'oauth_nonce' => nonce,
38
+ 'oauth_verifier' => options[:oauth_verifier],
37
39
  'oauth_version' => '1.0'
38
40
  }.reject { |k,v| v.to_s == "" }
39
41
  end
@@ -11,6 +11,12 @@ class Net::HTTPRequest
11
11
  # this may add a header, additional query string parameters, or additional POST body parameters.
12
12
  # The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
13
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+)
14
20
  #
15
21
  # This method also modifies the <tt>User-Agent</tt> header to add the OAuth gem version.
16
22
  #
@@ -34,7 +40,13 @@ class Net::HTTPRequest
34
40
  # on the <tt>options[:scheme]</tt> being used so this must match what will be used for the request
35
41
  # itself. The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
36
42
  # header.
37
- #
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
+ #
38
50
  # See Also: {OAuth core spec version 1.0, section 9.1.1}[http://oauth.net/core/1.0#rfc.section.9.1.1]
39
51
  def signature_base_string(http, consumer = nil, token = nil, options = {})
40
52
  options = { :request_uri => oauth_full_request_uri(http),
@@ -25,6 +25,7 @@ module OAuth
25
25
  :authorize_path => '/oauth/authorize',
26
26
  :access_token_path => '/oauth/access_token',
27
27
 
28
+ :proxy => nil,
28
29
  # How do we send the oauth values to the server see
29
30
  # http://oauth.net/core/1.0/#consumer_req_param for more info
30
31
  #
@@ -97,18 +98,40 @@ module OAuth
97
98
  end
98
99
  end
99
100
 
101
+ def get_access_token(request_token, request_options = {}, *arguments)
102
+ response = token_request(http_method, (access_token_url? ? access_token_url : access_token_path), request_token, request_options, *arguments)
103
+ OAuth::AccessToken.from_hash(self, response)
104
+ end
105
+
100
106
  # Makes a request to the service for a new OAuth::RequestToken
101
107
  #
102
108
  # @request_token = @consumer.get_request_token
103
109
  #
110
+ # To include OAuth parameters:
111
+ #
112
+ # @request_token = @consumer.get_request_token \
113
+ # :oauth_callback => "http://example.com/cb"
114
+ #
115
+ # To include application-specific parameters:
116
+ #
117
+ # @request_token = @consumer.get_request_token({}, :foo => "bar")
118
+ #
119
+ # TODO oauth_callback should be a mandatory parameter
104
120
  def get_request_token(request_options = {}, *arguments)
121
+ # if oauth_callback wasn't provided, it is assumed that oauth_verifiers
122
+ # will be exchanged out of band
123
+ request_options[:oauth_callback] ||= OAuth::OUT_OF_BAND
124
+
105
125
  response = token_request(http_method, (request_token_url? ? request_token_url : request_token_path), nil, request_options, *arguments)
106
- OAuth::RequestToken.new(self, response[:oauth_token], response[:oauth_token_secret])
126
+ OAuth::RequestToken.from_hash(self, response)
107
127
  end
108
128
 
109
129
  # Creates, signs and performs an http request.
110
130
  # It's recommended to use the OAuth::Token classes to set this up correctly.
111
- # The arguments parameters are a hash or string encoded set of parameters if it's a post request as well as optional http headers.
131
+ # request_options take precedence over consumer-wide options when signing
132
+ # a request.
133
+ # arguments are POST and PUT bodies (a Hash, string-encoded parameters, or
134
+ # absent), followed by additional HTTP headers.
112
135
  #
113
136
  # @consumer.request(:get, '/people', @token, { :scheme => :query_string })
114
137
  # @consumer.request(:post, '/people', @token, {}, @person.to_xml, { 'Content-Type' => 'application/xml' })
@@ -159,7 +182,14 @@ module OAuth
159
182
  case response.code.to_i
160
183
 
161
184
  when (200..299)
162
- CGI.parse(response.body).inject({}) { |h,(k,v)| h[k.to_sym] = v.first; h }
185
+ # symbolize keys
186
+ # TODO this could be considered unexpected behavior; symbols or not?
187
+ # TODO this also drops subsequent values from multi-valued keys
188
+ CGI.parse(response.body).inject({}) do |h,(k,v)|
189
+ h[k.to_sym] = v.first
190
+ h[k] = v.first
191
+ h
192
+ end
163
193
  when (300..399)
164
194
  # this is a redirect
165
195
  response.error!
@@ -225,6 +255,10 @@ module OAuth
225
255
  @options.has_key?(:access_token_url)
226
256
  end
227
257
 
258
+ def proxy
259
+ @options[:proxy]
260
+ end
261
+
228
262
  protected
229
263
 
230
264
  # Instantiates the http object
@@ -235,7 +269,12 @@ module OAuth
235
269
  our_uri = URI.parse(_url)
236
270
  end
237
271
 
238
- http_object = Net::HTTP.new(our_uri.host, our_uri.port)
272
+ if proxy.nil?
273
+ http_object = Net::HTTP.new(our_uri.host, our_uri.port)
274
+ else
275
+ proxy_uri = proxy.is_a?(URI) ? proxy : URI.parse(proxy)
276
+ http_object = Net::HTTP.new(our_uri.host, our_uri.port, proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
277
+ end
239
278
 
240
279
  http_object.use_ssl = (our_uri.scheme == 'https')
241
280
 
@@ -255,7 +294,7 @@ module OAuth
255
294
  http_method = http_method.to_sym
256
295
 
257
296
  if [:post, :put].include?(http_method)
258
- data = arguments.shift
297
+ data = (arguments.shift || {}).reject { |k,v| v.nil? }
259
298
  end
260
299
 
261
300
  headers = arguments.first.is_a?(Hash) ? arguments.shift : {}
@@ -280,8 +319,19 @@ module OAuth
280
319
  if data.is_a?(Hash)
281
320
  request.set_form_data(data)
282
321
  elsif data
283
- request.body = data.to_s
284
- request["Content-Length"] = request.body.length
322
+ if data.respond_to?(:read)
323
+ request.body_stream = data
324
+ if data.respond_to?(:length)
325
+ request["Content-Length"] = data.length
326
+ elsif data.respond_to?(:stat) && data.stat.respond_to?(:size)
327
+ request["Content-Length"] = data.stat.size
328
+ else
329
+ raise ArgumentError, "Don't know how to send a body_stream that doesn't respond to .length or .stat.size"
330
+ end
331
+ else
332
+ request.body = data.to_s
333
+ request["Content-Length"] = request.body.length
334
+ end
285
335
  end
286
336
 
287
337
  request
@@ -1,6 +1,10 @@
1
1
  module OAuth
2
+ # request tokens are passed between the consumer and the provider out of
3
+ # band (i.e. callbacks cannot be used), per section 6.1.1
4
+ OUT_OF_BAND = "oob"
5
+
2
6
  # required parameters, per sections 6.1.1, 6.3.1, and 7
3
- PARAMETERS = %w(oauth_consumer_key oauth_token oauth_signature_method oauth_timestamp oauth_nonce oauth_version oauth_signature)
7
+ PARAMETERS = %w(oauth_callback oauth_consumer_key oauth_token oauth_signature_method oauth_timestamp oauth_nonce oauth_verifier oauth_version oauth_signature)
4
8
 
5
9
  # reserved character regexp, per section 5.1
6
10
  RESERVED_CHARACTERS = /[^a-zA-Z0-9\-\.\_\~]/
@@ -1,4 +1,5 @@
1
1
  require 'active_support'
2
+ require 'action_controller'
2
3
  require 'action_controller/request'
3
4
  require 'oauth/request_proxy/base'
4
5
  require 'uri'
@@ -18,6 +18,10 @@ module OAuth::RequestProxy
18
18
 
19
19
  ## OAuth parameters
20
20
 
21
+ def oauth_callback
22
+ parameters['oauth_callback']
23
+ end
24
+
21
25
  def oauth_consumer_key
22
26
  parameters['oauth_consumer_key']
23
27
  end
@@ -48,6 +52,10 @@ module OAuth::RequestProxy
48
52
  parameters['oauth_token']
49
53
  end
50
54
 
55
+ def oauth_verifier
56
+ parameters['oauth_verifier']
57
+ end
58
+
51
59
  def oauth_version
52
60
  parameters["oauth_version"]
53
61
  end
@@ -13,6 +13,7 @@ module OAuth
13
13
  def initialize(consumer, token="", secret="")
14
14
  super(token, secret)
15
15
  @consumer = consumer
16
+ @params = {}
16
17
  end
17
18
 
18
19
  # Make a signed request using given http_method to the path
@@ -9,6 +9,10 @@ module OAuth
9
9
  build_authorize_url(consumer.authorize_url, params)
10
10
  end
11
11
 
12
+ def callback_confirmed?
13
+ params[:oauth_callback_confirmed] == "true"
14
+ end
15
+
12
16
  # exchange for AccessToken on server
13
17
  def get_access_token(options = {}, *arguments)
14
18
  response = consumer.token_request(consumer.http_method, (consumer.access_token_url? ? consumer.access_token_url : consumer.access_token_path), self, options, *arguments)
@@ -1,3 +1,3 @@
1
1
  module OAuth #:nodoc:
2
- VERSION = '0.3.4'
2
+ VERSION = '0.3.5'
3
3
  end
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{oauth}
5
- s.version = "0.3.4"
5
+ s.version = "0.3.5"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Pelle Braendgaard", "Blaine Cook", "Larry Halff", "Jesse Clark", "Jon Crosby", "Seth Fitzsimmons", "Matt Sanford"]
9
- s.date = %q{2009-05-06}
9
+ s.date = %q{2009-06-03}
10
10
  s.default_executable = %q{oauth}
11
11
  s.description = %q{OAuth Core Ruby implementation}
12
12
  s.email = %q{oauth-ruby@googlegroups.com}
@@ -1,6 +1,7 @@
1
1
  require File.dirname(__FILE__) + '/test_helper'
2
2
  require 'oauth/consumer'
3
3
  require 'oauth/signature/rsa/sha1'
4
+ require 'stringio'
4
5
 
5
6
 
6
7
  # This performs testing against Andy Smith's test server http://term.ie/oauth/example/
@@ -12,6 +13,7 @@ class ConsumerTest < Test::Unit::TestCase
12
13
  'consumer_key_86cad9', '5888bf0345e5d237',
13
14
  {
14
15
  :site=>"http://blabla.bla",
16
+ :proxy=>"http://user:password@proxy.bla:8080",
15
17
  :request_token_path=>"/oauth/example/request_token.php",
16
18
  :access_token_path=>"/oauth/example/access_token.php",
17
19
  :authorize_path=>"/oauth/example/authorize.php",
@@ -30,6 +32,7 @@ class ConsumerTest < Test::Unit::TestCase
30
32
  assert_equal "consumer_key_86cad9",@consumer.key
31
33
  assert_equal "5888bf0345e5d237",@consumer.secret
32
34
  assert_equal "http://blabla.bla",@consumer.site
35
+ assert_equal "http://user:password@proxy.bla:8080",@consumer.proxy
33
36
  assert_equal "/oauth/example/request_token.php",@consumer.request_token_path
34
37
  assert_equal "/oauth/example/access_token.php",@consumer.access_token_path
35
38
  assert_equal "http://blabla.bla/oauth/example/request_token.php",@consumer.request_token_url
@@ -49,6 +52,7 @@ class ConsumerTest < Test::Unit::TestCase
49
52
  assert_equal "key",@consumer.key
50
53
  assert_equal "secret",@consumer.secret
51
54
  assert_equal "http://twitter.com",@consumer.site
55
+ assert_nil @consumer.proxy
52
56
  assert_equal "/oauth/request_token",@consumer.request_token_path
53
57
  assert_equal "/oauth/access_token",@consumer.access_token_path
54
58
  assert_equal "http://twitter.com/oauth/request_token",@consumer.request_token_url
@@ -318,10 +322,43 @@ class ConsumerTest < Test::Unit::TestCase
318
322
  debug)
319
323
  end
320
324
 
325
+ def test_post_with_body_stream
326
+ @consumer=OAuth::Consumer.new(
327
+ "key",
328
+ "secret",
329
+ {
330
+ :site=>"http://term.ie",
331
+ :request_token_path=>"/oauth/example/request_token.php",
332
+ :access_token_path=>"/oauth/example/access_token.php",
333
+ :authorize_path=>"/oauth/example/authorize.php"
334
+ })
335
+
336
+
337
+ @request_token=@consumer.get_request_token
338
+ @access_token=@request_token.get_access_token
339
+
340
+ request_body_string = "Hello, hello, hello"
341
+ request_body_stream = StringIO.new( request_body_string )
342
+
343
+ @response=@access_token.post("/oauth/example/echo_api.php",request_body_stream)
344
+ assert_not_nil @response
345
+ assert_equal "200",@response.code
346
+
347
+ request_body_file = File.open(__FILE__)
348
+
349
+ @response=@access_token.post("/oauth/example/echo_api.php",request_body_file)
350
+ assert_not_nil @response
351
+ assert_equal "200",@response.code
352
+
353
+ # unfortunately I don't know of a way to test that the body data was received correctly since the test server at http://term.ie
354
+ # echos back any non-oauth parameters but not the body. However, this does test that the request is still correctly signed
355
+ # (including the Content-Length header) and that the server received Content-Length bytes of body since it won't process the
356
+ # request & respond until the full body length is received.
357
+ end
358
+
321
359
  protected
322
360
 
323
361
  def request_parameters_to_s
324
362
  @request_parameters.map { |k,v| "#{k}=#{v}" }.join("&")
325
363
  end
326
-
327
364
  end
@@ -33,7 +33,7 @@
33
33
  <h1>Ruby OAuth GEM</h1>
34
34
  <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/oauth"; return false'>
35
35
  <p>Get Version</p>
36
- <a href="http://rubyforge.org/projects/oauth" class="numbers">0.3.4</a>
36
+ <a href="http://rubyforge.org/projects/oauth" class="numbers">0.3.5</a>
37
37
  </div>
38
38
  <h2>What</h2>
39
39
  <p>This is a RubyGem for implementing both OAuth clients and servers in Ruby applications.</p>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oauth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pelle Braendgaard
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2009-05-06 00:00:00 +05:30
17
+ date: 2009-06-03 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency