oauth 0.3.1 → 0.3.2

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.

Files changed (50) hide show
  1. data/History.txt +35 -17
  2. data/Manifest.txt +13 -1
  3. data/README.rdoc +5 -7
  4. data/Rakefile +6 -4
  5. data/TODO +18 -0
  6. data/bin/oauth +1 -1
  7. data/examples/yql.rb +44 -0
  8. data/lib/oauth.rb +1 -0
  9. data/lib/oauth/cli.rb +201 -31
  10. data/lib/oauth/client/action_controller_request.rb +13 -12
  11. data/lib/oauth/client/helper.rb +10 -14
  12. data/lib/oauth/client/net_http.rb +25 -22
  13. data/lib/oauth/consumer.rb +164 -110
  14. data/lib/oauth/errors.rb +3 -0
  15. data/lib/oauth/errors/error.rb +4 -0
  16. data/lib/oauth/errors/problem.rb +14 -0
  17. data/lib/oauth/errors/unauthorized.rb +12 -0
  18. data/lib/oauth/helper.rb +44 -6
  19. data/lib/oauth/oauth.rb +7 -0
  20. data/lib/oauth/oauth_test_helper.rb +12 -13
  21. data/lib/oauth/request_proxy/action_controller_request.rb +5 -6
  22. data/lib/oauth/request_proxy/base.rb +95 -45
  23. data/lib/oauth/request_proxy/jabber_request.rb +1 -2
  24. data/lib/oauth/request_proxy/mock_request.rb +8 -0
  25. data/lib/oauth/request_proxy/net_http.rb +2 -2
  26. data/lib/oauth/request_proxy/rack_request.rb +7 -7
  27. data/lib/oauth/server.rb +31 -33
  28. data/lib/oauth/signature/base.rb +23 -21
  29. data/lib/oauth/signature/hmac/base.rb +1 -1
  30. data/lib/oauth/signature/hmac/sha1.rb +0 -1
  31. data/lib/oauth/signature/plaintext.rb +2 -2
  32. data/lib/oauth/signature/rsa/sha1.rb +5 -4
  33. data/lib/oauth/token.rb +6 -136
  34. data/lib/oauth/tokens/access_token.rb +68 -0
  35. data/lib/oauth/tokens/consumer_token.rb +32 -0
  36. data/lib/oauth/tokens/request_token.rb +28 -0
  37. data/lib/oauth/tokens/server_token.rb +9 -0
  38. data/lib/oauth/tokens/token.rb +17 -0
  39. data/lib/oauth/version.rb +1 -1
  40. data/oauth.gemspec +12 -6
  41. data/test/cases/spec/1_0-final/test_construct_request_url.rb +1 -1
  42. data/test/test_access_token.rb +28 -0
  43. data/test/test_action_controller_request_proxy.rb +17 -0
  44. data/test/test_consumer.rb +3 -4
  45. data/test/test_helper.rb +0 -5
  46. data/test/test_request_token.rb +53 -0
  47. data/test/test_server.rb +1 -1
  48. data/website/index.html +2 -2
  49. metadata +37 -4
  50. data/specs.txt +0 -13
@@ -1,8 +1,23 @@
1
- == 0.3.1
1
+ == 0.3.2 2009-03-23
2
2
 
3
- * Michael Wood identified a problem with relative and absolute token request paths. This should now be fixed and is tested for both cases.
3
+ * 2xx statuses should be treated as success (Anders Conbere)
4
+ * Support applications using the MethodOverride Rack middleware (László Bácsi)
5
+ * `authorize` command for `oauth` CLI (Seth)
6
+ * Initial support for Problem Reporting extension (Seth)
7
+ * Verify SSL certificates if CA certificates are available (Seth)
8
+ * Fixed ActionController parameter escaping behavior (Thiago Arrais, László
9
+ Bácsi, Brett Gibson, et al)
10
+ * Fixed signature calculation when both options and a block were provided to
11
+ OAuth::Signature::Base#initialize (Seth)
12
+ * Added help to the 'oauth' CLI (Seth)
13
+ * Fixed a problem when attempting to normalize MockRequest URIs (Seth)
4
14
 
5
- == 0.3.0
15
+ == 0.3.1 2009-1-26
16
+
17
+ * Fixed a problem with relative and absolute token request paths. (Michael
18
+ Wood)
19
+
20
+ == 0.3.0 2009-1-25
6
21
 
7
22
  * Support ActionController::Request from Edge Rails (László Bácsi)
8
23
  * Correctly handle multi-valued parameters (Seth)
@@ -15,23 +30,25 @@
15
30
  * Improved test-cases and compatibility for encoding issues. (Pelle)
16
31
 
17
32
  == 0.2.7 2008-9-10 The lets fix the last release release
18
- Fix in plain text signatures to bug found by Andrew Arrow. Who contributed new new unit tests for plain text sigs.
19
33
 
20
- There was an error in the RSA requests using oauth tokens. Thanks to Philip Lipu Tsai for noticing this.
34
+ * Fixed plain text signatures (Andrew Arrow)
35
+ * Fixed RSA requests using OAuthTokens. (Philip Lipu Tsai)
21
36
 
22
37
  == 0.2.6 2008-9-9 The lets RSA release
23
38
 
24
- - Bill Kocik's fix for Ruby 1.8.7
25
- - Fixed rsa verification, so you can actually create an OAuth server yourself now using Ruby and RSA
26
- - Added better testing for RSA
27
- - Fixed issue where token was being included for rsa signatures
28
- - Chris Mear added support for a private_key_file option for rsa signatures
29
- - Scott Hill fixed several edge cases where parameters were incorrectly being signed
30
- - Patch from choonkeat fixing a problem with rsa signing.
39
+ * Improved support for Ruby 1.8.7 (Bill Kocik)
40
+ * Fixed RSA verification to support RSA providers
41
+ now using Ruby and RSA
42
+ * Improved RSA testing
43
+ * Omit token when signing with RSA
44
+ * Added support for 'private_key_file' option for RSA signatures (Chris Mear)
45
+ * Fixed several edge cases where params were being incorrectly signed (Scott
46
+ Hill)
47
+ * Fixed RSA signing (choonkeat)
31
48
 
32
49
  == 0.2.2 2008-2-22 Lets actually support SSL release
33
50
 
34
- It didn't actually use https when required.
51
+ * Use HTTPS when required.
35
52
 
36
53
  == 0.2 2008-1-19 All together now release
37
54
 
@@ -39,10 +56,11 @@ This is a big release, where we have merged the efforts of various parties into
39
56
 
40
57
  == 0.1.2 2007-12-1
41
58
 
42
- * 1 Fixed a problem where incoming request didn't check whether oauth parameters where missing. While not giving unauthorized access it did cause extra processing where not necessary.
43
- * 2 Includes Pat's fix for getting the realm out.
59
+ * Fixed checks for missing OAuth params to improve performance
60
+ * Includes Pat's fix for getting the realm out.
44
61
 
45
62
  == 0.1.1 2007-11-26
46
63
 
47
- * 1 First release as a GEM
48
- * Moved all non rails functions into this GEM from the Rails plugin http://code.google.com/p/oauth-plugin/
64
+ * First release as a GEM
65
+ * Moved all non-Rails functionality from the Rails plugin:
66
+ http://code.google.com/p/oauth-plugin/
@@ -5,13 +5,19 @@ README.rdoc
5
5
  Rakefile
6
6
  TODO
7
7
  bin/oauth
8
+ examples/yql.rb
8
9
  lib/oauth.rb
10
+ lib/oauth/oauth.rb
9
11
  lib/oauth/cli.rb
10
12
  lib/oauth/client.rb
11
13
  lib/oauth/client/action_controller_request.rb
12
14
  lib/oauth/client/helper.rb
13
15
  lib/oauth/client/net_http.rb
14
16
  lib/oauth/consumer.rb
17
+ lib/oauth/errors.rb
18
+ lib/oauth/errors/error.rb
19
+ lib/oauth/errors/problem.rb
20
+ lib/oauth/errors/unauthorized.rb
15
21
  lib/oauth/helper.rb
16
22
  lib/oauth/oauth_test_helper.rb
17
23
  lib/oauth/request_proxy.rb
@@ -34,13 +40,17 @@ lib/oauth/signature/plaintext.rb
34
40
  lib/oauth/signature/rsa/sha1.rb
35
41
  lib/oauth/signature/sha1.rb
36
42
  lib/oauth/token.rb
43
+ lib/oauth/tokens/access_token.rb
44
+ lib/oauth/tokens/consumer_token.rb
45
+ lib/oauth/tokens/request_token.rb
46
+ lib/oauth/tokens/server_token.rb
47
+ lib/oauth/tokens/token.rb
37
48
  lib/oauth/version.rb
38
49
  oauth.gemspec
39
50
  script/destroy
40
51
  script/generate
41
52
  script/txt2html
42
53
  setup.rb
43
- specs.txt
44
54
  tasks/deployment.rake
45
55
  tasks/environment.rake
46
56
  tasks/website.rake
@@ -51,6 +61,7 @@ test/cases/spec/1_0-final/test_parameter_encodings.rb
51
61
  test/cases/spec/1_0-final/test_signature_base_strings.rb
52
62
  test/keys/rsa.cert
53
63
  test/keys/rsa.pem
64
+ test/test_access_token.rb
54
65
  test/test_action_controller_request_proxy.rb
55
66
  test/test_consumer.rb
56
67
  test/test_helper.rb
@@ -58,6 +69,7 @@ test/test_hmac_sha1.rb
58
69
  test/test_net_http_client.rb
59
70
  test/test_net_http_request_proxy.rb
60
71
  test/test_rack_request_proxy.rb
72
+ test/test_request_token.rb
61
73
  test/test_rsa_sha1.rb
62
74
  test/test_server.rb
63
75
  test/test_signature.rb
@@ -24,20 +24,18 @@ As a matter of fact it has been pulled out from an OAuth Rails Plugin http://cod
24
24
 
25
25
  Create a new consumer instance by passing it a configuration hash:
26
26
 
27
- @consumer=OAuth::Consumer.new( "key","secret", {
28
- :site=>"https://agree2"
29
- })
27
+ @consumer = OAuth::Consumer.new("key","secret", :site => "https://agree2")
30
28
 
31
29
  Start the process by requesting a token
32
30
 
33
- @request_token=@consumer.get_request_token
34
- session[:request_token]=@request_token
31
+ @request_token = @consumer.get_request_token
32
+ session[:request_token] = @request_token
35
33
  redirect_to @request_token.authorize_url
36
34
 
37
35
  When user returns create an access_token
38
36
 
39
- @access_token=@request_token.get_access_token
40
- @photos=@access_token.get('/photos.xml')
37
+ @access_token = @request_token.get_access_token
38
+ @photos = @access_token.get('/photos.xml')
41
39
 
42
40
  For more detailed instructions I have written this OAuth Client Tutorial http://stakeventures.com/articles/2008/02/23/developing-oauth-clients-in-ruby and "How to turn your rails site into an OAuth Provider ":http://stakeventures.com/articles/2007/11/26/how-to-turn-your-rails-site-into-an-oauth-provider .
43
41
 
data/Rakefile CHANGED
@@ -6,21 +6,23 @@ require 'oauth/version'
6
6
  # Generate all the Rake tasks
7
7
  # Run 'rake -T' to see list of generated tasks (from gem root directory)
8
8
  $hoe = Hoe.new('oauth', OAuth::VERSION) do |p|
9
- p.author = ['Pelle Braendgaard','Blaine Cook','Larry Halff','Jesse Clark','Jon Crosby', 'Seth Fitzsimmons']
9
+ p.author = ['Pelle Braendgaard','Blaine Cook','Larry Halff','Jesse Clark','Jon Crosby', 'Seth Fitzsimmons']
10
10
  p.email = "pelleb@gmail.com"
11
11
  p.description = "OAuth Core Ruby implementation"
12
12
  p.summary = p.description
13
13
  p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
14
14
  p.rubyforge_name = p.name # TODO this is default value
15
15
  p.url = "http://oauth.rubyforge.org"
16
-
16
+
17
17
  p.extra_deps = [
18
18
  ['ruby-hmac','>= 0.3.1']
19
19
  ]
20
20
  p.extra_dev_deps = [
21
- ['newgem', ">= #{::Newgem::VERSION}"]
21
+ ['newgem', ">= #{::Newgem::VERSION}"],
22
+ ['actionpack'],
23
+ ['rack']
22
24
  ]
23
-
25
+
24
26
  p.clean_globs |= %w[**/.DS_Store tmp *.log **/.*.sw? *.gem .config **/.DS_Store]
25
27
  path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
26
28
  p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
data/TODO CHANGED
@@ -12,3 +12,21 @@ Common use-cases should be streamlined:
12
12
  errors, if available).
13
13
  * I want to host an OAuth-enabled web service.
14
14
  * I want to test my OAuth-enabled web service (i.e. test helpers)
15
+
16
+ Example applications for:
17
+ * Ning
18
+ * Fire Eagle
19
+ * Google (blogger, contacts)
20
+ * Twitter
21
+ * YOS / YQL
22
+ * Netflix
23
+
24
+ In addition to providing best practices of use, these can also be part of
25
+ the pre-release checks to make sure that there have been no regressions.
26
+
27
+ Random TODOs:
28
+ * finish CLI
29
+ * sensible Exception hierarchy
30
+ * User Agent
31
+ * Tokens as Modules
32
+ * don't tie to Net::HTTP
data/bin/oauth CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  require "oauth/cli"
4
4
 
5
- OAuth::CLI.execute(STDOUT, ARGV)
5
+ OAuth::CLI.execute(STDOUT, STDIN, STDERR, ARGV)
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env ruby -rubygems
2
+
3
+ # Sample queries:
4
+ # ./yql.rb --consumer-key <key> --consumer-secret <secret> "show tables"
5
+ # ./yql.rb --consumer-key <key> --consumer-secret <secret> "select * from flickr.photos.search where text='Cat' limit 10"
6
+
7
+ require 'oauth'
8
+ require 'optparse'
9
+ require 'json'
10
+ require 'pp'
11
+
12
+ options = {}
13
+
14
+ option_parser = OptionParser.new do |opts|
15
+ opts.banner = "Usage: #{$0} [options] <query>"
16
+
17
+ opts.on("--consumer-key KEY", "Specifies the consumer key to use.") do |v|
18
+ options[:consumer_key] = v
19
+ end
20
+
21
+ opts.on("--consumer-secret SECRET", "Specifies the consumer secret to use.") do |v|
22
+ options[:consumer_secret] = v
23
+ end
24
+ end
25
+
26
+ option_parser.parse!
27
+ query = ARGV.pop
28
+ query = STDIN.read if query == "-"
29
+
30
+ if options[:consumer_key].nil? || options[:consumer_secret].nil? || query.nil?
31
+ puts option_parser.help
32
+ exit 1
33
+ end
34
+
35
+ consumer = OAuth::Consumer.new \
36
+ options[:consumer_key],
37
+ options[:consumer_secret],
38
+ :site => "http://query.yahooapis.com"
39
+
40
+ access_token = OAuth::AccessToken.new(consumer)
41
+
42
+ response = access_token.request(:get, url = "/v1/yql?q=#{OAuth::Helper.escape(query)}&format=json")
43
+ rsp = JSON.parse(response.body)
44
+ pp rsp
@@ -1,3 +1,4 @@
1
+ require 'oauth/oauth'
1
2
  require 'oauth/client/helper'
2
3
  require 'oauth/signature/hmac/sha1'
3
4
  require 'oauth/request_proxy/mock_request'
@@ -3,48 +3,136 @@ require 'oauth'
3
3
 
4
4
  module OAuth
5
5
  class CLI
6
- SUPPORTED_COMMANDS = %w(sign)
6
+ SUPPORTED_COMMANDS = {
7
+ "authorize" => "Obtain an access token and secret for a user",
8
+ "debug" => "Verbosely generate an OAuth signature",
9
+ "sign" => "Generate an OAuth signature"
10
+ }
7
11
 
8
12
  attr_reader :command
9
13
  attr_reader :options
10
- attr_reader :stdout
14
+ attr_reader :stdout, :stdin
11
15
 
12
- def self.execute(stdout, arguments = [])
13
- self.new.execute(stdout, arguments)
16
+ def self.execute(stdout, stdin, stderr, arguments = [])
17
+ self.new.execute(stdout, stdin, stderr, arguments)
14
18
  end
15
19
 
16
- def execute(stdout, arguments = [])
20
+ def initialize
21
+ @options = {}
22
+
23
+ # don't dump a backtrace on a ^C
24
+ trap(:INT) {
25
+ exit
26
+ }
27
+ end
28
+
29
+ def execute(stdout, stdin, stderr, arguments = [])
17
30
  @stdout = stdout
31
+ @stdin = stdin
32
+ @stderr = stderr
18
33
  extract_command_and_parse_options(arguments)
19
34
 
20
35
  if sufficient_options? && valid_command?
36
+ if command == "debug"
37
+ @command = "sign"
38
+ @options[:verbose] = true
39
+ end
40
+
21
41
  case command
42
+ # TODO move command logic elsewhere
43
+ 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
54
+
55
+ # get a request token
56
+ request_token = consumer.get_request_token
57
+
58
+ stdout.puts "Please visit this url to authorize:"
59
+ stdout.puts request_token.authorize_url
60
+
61
+ stdout.puts "Press return to continue..."
62
+ stdin.gets
63
+
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}"
71
+ end
72
+ rescue OAuth::Unauthorized => e
73
+ stderr.puts "A problem occurred while attempting to obtain an access token:"
74
+ stderr.puts e
75
+ end
22
76
  when "sign"
77
+ parameters = prepare_parameters
78
+
23
79
  request = OAuth::RequestProxy.proxy \
24
80
  "method" => options[:method],
25
81
  "uri" => options[:uri],
26
- "parameters" => prepare_parameters
82
+ "parameters" => parameters
27
83
 
28
- # can't pass options unless they respond to :secret, so use this alternative
29
- signature = OAuth::Signature.sign \
30
- request,
31
- :consumer_secret => options[:oauth_consumer_secret],
32
- :token_secret => options[:oauth_token_secret] do |request|
33
-
34
- # while we have access to the request being signed, display some internals
35
- if verbose?
36
- stdout.puts "Method: #{request.method}"
37
- stdout.puts "URI: #{request.uri}"
38
- stdout.puts "Normalized params: #{request.normalized_parameters}"
39
- stdout.puts "Signature base string: #{request.signature_base_string}"
84
+ if verbose?
85
+ stdout.puts "OAuth parameters:"
86
+ request.oauth_parameters.each do |k,v|
87
+ stdout.puts " " + [k, v] * ": "
88
+ end
89
+ stdout.puts
90
+
91
+ if request.non_oauth_parameters.any?
92
+ stdout.puts "Parameters:"
93
+ request.non_oauth_parameters.each do |k,v|
94
+ stdout.puts " " + [k, v] * ": "
95
+ end
96
+ stdout.puts
40
97
  end
41
98
  end
42
99
 
100
+ request.sign! \
101
+ :consumer_secret => options[:oauth_consumer_secret],
102
+ :token_secret => options[:oauth_token_secret]
103
+
43
104
  if verbose?
44
- stdout.puts "Signature: #{signature}"
45
- stdout.puts "Escaped signature: #{OAuth::Helper.escape(signature)}"
105
+ stdout.puts "Method: #{request.method}"
106
+ stdout.puts "URI: #{request.uri}"
107
+ stdout.puts "Normalized params: #{request.normalized_parameters}" unless options[:xmpp]
108
+ stdout.puts "Signature base string: #{request.signature_base_string}"
109
+
110
+ if options[:xmpp]
111
+ stdout.puts
112
+ stdout.puts "XMPP Stanza:"
113
+ stdout.puts <<-EOS
114
+ <oauth xmlns='urn:xmpp:tmp:oauth'>
115
+ <oauth_consumer_key>#{request.oauth_consumer_key}</oauth_consumer_key>
116
+ <oauth_token>#{request.oauth_token}</oauth_token>
117
+ <oauth_signature_method>#{request.oauth_signature_method}</oauth_signature_method>
118
+ <oauth_signature>#{request.oauth_signature}</oauth_signature>
119
+ <oauth_timestamp>#{request.oauth_timestamp}</oauth_timestamp>
120
+ <oauth_nonce>#{request.oauth_nonce}</oauth_nonce>
121
+ <oauth_version>#{request.oauth_version}</oauth_version>
122
+ </oauth>
123
+ EOS
124
+ stdout.puts
125
+ stdout.puts "Note: You may want to use bare JIDs in your URI."
126
+ stdout.puts
127
+ else
128
+ stdout.puts "OAuth Request URI: #{request.signed_uri}"
129
+ stdout.puts "Request URI: #{request.signed_uri(false)}"
130
+ stdout.puts "Authorization header: #{request.oauth_header(:realm => options[:realm])}"
131
+ end
132
+ stdout.puts "Signature: #{request.oauth_signature}"
133
+ stdout.puts "Escaped signature: #{OAuth::Helper.escape(request.oauth_signature)}"
46
134
  else
47
- stdout.puts signature
135
+ stdout.puts request.oauth_signature
48
136
  end
49
137
  end
50
138
  else
@@ -52,18 +140,25 @@ module OAuth
52
140
  end
53
141
  end
54
142
 
143
+ protected
144
+
55
145
  def extract_command_and_parse_options(arguments)
56
146
  @command = arguments[-1]
57
147
  parse_options(arguments[0..-1])
58
148
  end
59
149
 
60
- def parse_options(arguments)
61
- @options = {}
62
- OptionParser.new do |opts|
150
+ def option_parser
151
+ option_parser = OptionParser.new do |opts|
63
152
  opts.banner = "Usage: #{$0} [options] <command>"
64
153
 
65
154
  # defaults
155
+ options[:oauth_nonce] = OAuth::Helper.generate_key
66
156
  options[:oauth_signature_method] = "HMAC-SHA1"
157
+ options[:oauth_timestamp] = OAuth::Helper.generate_timestamp
158
+ options[:oauth_version] = "1.0"
159
+ options[:params] = []
160
+
161
+ ## Common Options
67
162
 
68
163
  opts.on("--consumer-key KEY", "Specifies the consumer key to use.") do |v|
69
164
  options[:oauth_consumer_key] = v
@@ -73,12 +168,18 @@ module OAuth
73
168
  options[:oauth_consumer_secret] = v
74
169
  end
75
170
 
171
+ ## Options for signing
172
+
76
173
  opts.on("--method METHOD", "Specifies the method (e.g. GET) to use when signing.") do |v|
77
174
  options[:method] = v
78
175
  end
79
176
 
177
+ opts.on("--nonce NONCE", "Specifies the none to use.") do |v|
178
+ options[:oauth_nonce] = v
179
+ end
180
+
80
181
  opts.on("--parameters PARAMS", "Specifies the parameters to use when signing.") do |v|
81
- options[:params] = v
182
+ options[:params] << v
82
183
  end
83
184
 
84
185
  opts.on("--signature-method METHOD", "Specifies the signature method to use; defaults to HMAC-SHA1.") do |v|
@@ -89,38 +190,107 @@ module OAuth
89
190
  options[:oauth_token_secret] = v
90
191
  end
91
192
 
193
+ opts.on("--timestamp TIMESTAMP", "Specifies the timestamp to use.") do |v|
194
+ options[:oauth_timestamp] = v
195
+ end
196
+
92
197
  opts.on("--token TOKEN", "Specifies the token to use.") do |v|
93
198
  options[:oauth_token] = v
94
199
  end
95
200
 
201
+ opts.on("--realm REALM", "Specifies the realm to use.") do |v|
202
+ options[:realm] = v
203
+ end
204
+
96
205
  opts.on("--uri URI", "Specifies the URI to use when signing.") do |v|
97
206
  options[:uri] = v
98
207
  end
99
208
 
209
+ opts.on("--version VERSION", "Specifies the OAuth version to use.") do |v|
210
+ options[:oauth_version] = v
211
+ end
212
+
213
+ opts.on("--no-version", "Omit oauth_version.") do
214
+ options[:oauth_version] = nil
215
+ end
216
+
217
+ opts.on("--xmpp", "Generate XMPP stanzas.") do
218
+ options[:xmpp] = true
219
+ options[:method] ||= "iq"
220
+ end
221
+
100
222
  opts.on("-v", "--verbose", "Be verbose.") do
101
223
  options[:verbose] = true
102
224
  end
103
- end.parse!(arguments)
225
+
226
+ ## Options for authorization
227
+
228
+ opts.on("--access-token-url URL", "Specifies the access token URL.") do |v|
229
+ options[:access_token_url] = v
230
+ end
231
+
232
+ opts.on("--authorize-url URL", "Specifies the authorization URL.") do |v|
233
+ options[:authorize_url] = v
234
+ end
235
+
236
+ opts.on("--request-token-url URL", "Specifies the request token URL.") do |v|
237
+ options[:request_token_url] = v
238
+ end
239
+ end
240
+ end
241
+
242
+ def parse_options(arguments)
243
+ option_parser.parse!(arguments)
104
244
  end
105
245
 
106
246
  def prepare_parameters
247
+ escaped_pairs = options[:params].collect do |pair|
248
+ if pair =~ /:/
249
+ Hash[*pair.split(":", 2)].collect do |k,v|
250
+ [CGI.escape(k.strip), CGI.escape(v.strip)] * "="
251
+ end
252
+ else
253
+ pair
254
+ end
255
+ end
256
+
257
+ querystring = escaped_pairs * "&"
258
+ cli_params = CGI.parse(querystring)
259
+
107
260
  {
108
261
  "oauth_consumer_key" => options[:oauth_consumer_key],
262
+ "oauth_nonce" => options[:oauth_nonce],
263
+ "oauth_timestamp" => options[:oauth_timestamp],
109
264
  "oauth_token" => options[:oauth_token],
110
- "oauth_signature_method" => options[:oauth_signature_method]
111
- }.merge(CGI.parse(options[:params]))
265
+ "oauth_signature_method" => options[:oauth_signature_method],
266
+ "oauth_version" => options[:oauth_version]
267
+ }.reject { |k,v| v.nil? || v == "" }.merge(cli_params)
112
268
  end
113
269
 
114
270
  def sufficient_options?
115
- options[:oauth_consumer_key] && options[:oauth_consumer_secret] && options[:method] && options[:uri]
271
+ case command
272
+ # TODO move command logic elsewhere
273
+ when "authorize"
274
+ options[:oauth_consumer_key] && options[:oauth_consumer_secret] &&
275
+ options[:access_token_url] && options[:authorize_url] &&
276
+ options[:request_token_url]
277
+ else
278
+ options[:oauth_consumer_key] && options[:oauth_consumer_secret] &&
279
+ options[:method] && options[:uri]
280
+ end
116
281
  end
117
282
 
118
283
  def usage
119
- stdout.puts "Should be generated by OptionParser"
284
+ stdout.puts option_parser.help
285
+ stdout.puts
286
+ stdout.puts "Available commands:"
287
+ SUPPORTED_COMMANDS.each do |command, desc|
288
+ puts " #{command.ljust(15)}#{desc}"
289
+ end
120
290
  end
121
291
 
122
292
  def valid_command?
123
- SUPPORTED_COMMANDS.include?(command)
293
+ SUPPORTED_COMMANDS.keys.include?(command)
124
294
  end
125
295
 
126
296
  def verbose?