motionbox-oauth 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/.gemtest +0 -0
  2. data/Gemfile +16 -0
  3. data/Gemfile.lock +46 -0
  4. data/HISTORY +160 -0
  5. data/LICENSE +20 -0
  6. data/README.rdoc +75 -0
  7. data/Rakefile +37 -0
  8. data/TODO +32 -0
  9. data/bin/oauth +5 -0
  10. data/examples/yql.rb +44 -0
  11. data/lib/digest/hmac.rb +104 -0
  12. data/lib/oauth.rb +13 -0
  13. data/lib/oauth/cli.rb +378 -0
  14. data/lib/oauth/client.rb +4 -0
  15. data/lib/oauth/client/action_controller_request.rb +65 -0
  16. data/lib/oauth/client/em_http.rb +124 -0
  17. data/lib/oauth/client/helper.rb +91 -0
  18. data/lib/oauth/client/net_http.rb +120 -0
  19. data/lib/oauth/consumer.rb +382 -0
  20. data/lib/oauth/core_ext.rb +31 -0
  21. data/lib/oauth/errors.rb +3 -0
  22. data/lib/oauth/errors/error.rb +4 -0
  23. data/lib/oauth/errors/problem.rb +14 -0
  24. data/lib/oauth/errors/unauthorized.rb +12 -0
  25. data/lib/oauth/helper.rb +88 -0
  26. data/lib/oauth/oauth.rb +13 -0
  27. data/lib/oauth/oauth_test_helper.rb +25 -0
  28. data/lib/oauth/request_proxy.rb +24 -0
  29. data/lib/oauth/request_proxy/action_controller_request.rb +62 -0
  30. data/lib/oauth/request_proxy/base.rb +174 -0
  31. data/lib/oauth/request_proxy/curb_request.rb +55 -0
  32. data/lib/oauth/request_proxy/em_http_request.rb +74 -0
  33. data/lib/oauth/request_proxy/jabber_request.rb +41 -0
  34. data/lib/oauth/request_proxy/mock_request.rb +44 -0
  35. data/lib/oauth/request_proxy/net_http.rb +72 -0
  36. data/lib/oauth/request_proxy/rack_request.rb +44 -0
  37. data/lib/oauth/request_proxy/typhoeus_request.rb +53 -0
  38. data/lib/oauth/server.rb +66 -0
  39. data/lib/oauth/signature.rb +45 -0
  40. data/lib/oauth/signature/base.rb +110 -0
  41. data/lib/oauth/signature/hmac/base.rb +15 -0
  42. data/lib/oauth/signature/hmac/md5.rb +8 -0
  43. data/lib/oauth/signature/hmac/rmd160.rb +8 -0
  44. data/lib/oauth/signature/hmac/sha1.rb +9 -0
  45. data/lib/oauth/signature/hmac/sha2.rb +8 -0
  46. data/lib/oauth/signature/md5.rb +13 -0
  47. data/lib/oauth/signature/plaintext.rb +23 -0
  48. data/lib/oauth/signature/rsa/sha1.rb +46 -0
  49. data/lib/oauth/signature/sha1.rb +13 -0
  50. data/lib/oauth/token.rb +7 -0
  51. data/lib/oauth/tokens/access_token.rb +71 -0
  52. data/lib/oauth/tokens/consumer_token.rb +33 -0
  53. data/lib/oauth/tokens/request_token.rb +32 -0
  54. data/lib/oauth/tokens/server_token.rb +9 -0
  55. data/lib/oauth/tokens/token.rb +17 -0
  56. data/oauth.gemspec +150 -0
  57. data/tasks/deployment.rake +34 -0
  58. data/tasks/environment.rake +7 -0
  59. data/tasks/website.rake +17 -0
  60. data/test/cases/oauth_case.rb +19 -0
  61. data/test/cases/spec/1_0-final/test_construct_request_url.rb +62 -0
  62. data/test/cases/spec/1_0-final/test_normalize_request_parameters.rb +88 -0
  63. data/test/cases/spec/1_0-final/test_parameter_encodings.rb +86 -0
  64. data/test/cases/spec/1_0-final/test_signature_base_strings.rb +77 -0
  65. data/test/integration/consumer_test.rb +307 -0
  66. data/test/keys/rsa.cert +11 -0
  67. data/test/keys/rsa.pem +16 -0
  68. data/test/test_access_token.rb +26 -0
  69. data/test/test_action_controller_request_proxy.rb +133 -0
  70. data/test/test_consumer.rb +171 -0
  71. data/test/test_curb_request_proxy.rb +77 -0
  72. data/test/test_em_http_client.rb +80 -0
  73. data/test/test_em_http_request_proxy.rb +115 -0
  74. data/test/test_helper.rb +26 -0
  75. data/test/test_hmac_sha1.rb +20 -0
  76. data/test/test_net_http_client.rb +280 -0
  77. data/test/test_net_http_request_proxy.rb +72 -0
  78. data/test/test_oauth_helper.rb +71 -0
  79. data/test/test_rack_request_proxy.rb +40 -0
  80. data/test/test_request_token.rb +51 -0
  81. data/test/test_rsa_sha1.rb +59 -0
  82. data/test/test_server.rb +40 -0
  83. data/test/test_signature.rb +22 -0
  84. data/test/test_signature_base.rb +32 -0
  85. data/test/test_signature_plain_text.rb +31 -0
  86. data/test/test_token.rb +14 -0
  87. data/test/test_typhoeus_request_proxy.rb +80 -0
  88. metadata +284 -0
@@ -0,0 +1,9 @@
1
+ module OAuth
2
+ # Used on the server for generating tokens
3
+ class ServerToken < Token
4
+
5
+ def initialize
6
+ super(generate_key(16), generate_key)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ module OAuth
2
+ # Superclass for the various tokens used by OAuth
3
+ class Token
4
+ include OAuth::Helper
5
+
6
+ attr_accessor :token, :secret
7
+
8
+ def initialize(token, secret)
9
+ @token = token
10
+ @secret = secret
11
+ end
12
+
13
+ def to_query
14
+ "oauth_token=#{escape(token)}&oauth_secret=#{escape(secret)}"
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,150 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{motionbox-oauth}
8
+ s.version = "0.4.5"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Pelle Braendgaard", "Blaine Cook", "Larry Halff", "Jesse Clark", "Jon Crosby", "Seth Fitzsimmons", "Matt Sanford", "Aaron Quint"]
12
+ s.date = %q{2011-06-25}
13
+ s.default_executable = %q{oauth}
14
+ s.description = %q{OAuth Core Ruby implementation}
15
+ s.email = %q{oauth-ruby@googlegroups.com}
16
+ s.executables = ["oauth"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.rdoc",
20
+ "TODO"
21
+ ]
22
+ s.files = [
23
+ ".gemtest",
24
+ "Gemfile",
25
+ "Gemfile.lock",
26
+ "HISTORY",
27
+ "LICENSE",
28
+ "README.rdoc",
29
+ "Rakefile",
30
+ "TODO",
31
+ "bin/oauth",
32
+ "examples/yql.rb",
33
+ "lib/digest/hmac.rb",
34
+ "lib/oauth.rb",
35
+ "lib/oauth/cli.rb",
36
+ "lib/oauth/client.rb",
37
+ "lib/oauth/client/action_controller_request.rb",
38
+ "lib/oauth/client/em_http.rb",
39
+ "lib/oauth/client/helper.rb",
40
+ "lib/oauth/client/net_http.rb",
41
+ "lib/oauth/consumer.rb",
42
+ "lib/oauth/core_ext.rb",
43
+ "lib/oauth/errors.rb",
44
+ "lib/oauth/errors/error.rb",
45
+ "lib/oauth/errors/problem.rb",
46
+ "lib/oauth/errors/unauthorized.rb",
47
+ "lib/oauth/helper.rb",
48
+ "lib/oauth/oauth.rb",
49
+ "lib/oauth/oauth_test_helper.rb",
50
+ "lib/oauth/request_proxy.rb",
51
+ "lib/oauth/request_proxy/action_controller_request.rb",
52
+ "lib/oauth/request_proxy/base.rb",
53
+ "lib/oauth/request_proxy/curb_request.rb",
54
+ "lib/oauth/request_proxy/em_http_request.rb",
55
+ "lib/oauth/request_proxy/jabber_request.rb",
56
+ "lib/oauth/request_proxy/mock_request.rb",
57
+ "lib/oauth/request_proxy/net_http.rb",
58
+ "lib/oauth/request_proxy/rack_request.rb",
59
+ "lib/oauth/request_proxy/typhoeus_request.rb",
60
+ "lib/oauth/server.rb",
61
+ "lib/oauth/signature.rb",
62
+ "lib/oauth/signature/base.rb",
63
+ "lib/oauth/signature/hmac/base.rb",
64
+ "lib/oauth/signature/hmac/md5.rb",
65
+ "lib/oauth/signature/hmac/rmd160.rb",
66
+ "lib/oauth/signature/hmac/sha1.rb",
67
+ "lib/oauth/signature/hmac/sha2.rb",
68
+ "lib/oauth/signature/md5.rb",
69
+ "lib/oauth/signature/plaintext.rb",
70
+ "lib/oauth/signature/rsa/sha1.rb",
71
+ "lib/oauth/signature/sha1.rb",
72
+ "lib/oauth/token.rb",
73
+ "lib/oauth/tokens/access_token.rb",
74
+ "lib/oauth/tokens/consumer_token.rb",
75
+ "lib/oauth/tokens/request_token.rb",
76
+ "lib/oauth/tokens/server_token.rb",
77
+ "lib/oauth/tokens/token.rb",
78
+ "oauth.gemspec",
79
+ "tasks/deployment.rake",
80
+ "tasks/environment.rake",
81
+ "tasks/website.rake",
82
+ "test/cases/oauth_case.rb",
83
+ "test/cases/spec/1_0-final/test_construct_request_url.rb",
84
+ "test/cases/spec/1_0-final/test_normalize_request_parameters.rb",
85
+ "test/cases/spec/1_0-final/test_parameter_encodings.rb",
86
+ "test/cases/spec/1_0-final/test_signature_base_strings.rb",
87
+ "test/integration/consumer_test.rb",
88
+ "test/keys/rsa.cert",
89
+ "test/keys/rsa.pem",
90
+ "test/test_access_token.rb",
91
+ "test/test_action_controller_request_proxy.rb",
92
+ "test/test_consumer.rb",
93
+ "test/test_curb_request_proxy.rb",
94
+ "test/test_em_http_client.rb",
95
+ "test/test_em_http_request_proxy.rb",
96
+ "test/test_helper.rb",
97
+ "test/test_hmac_sha1.rb",
98
+ "test/test_net_http_client.rb",
99
+ "test/test_net_http_request_proxy.rb",
100
+ "test/test_oauth_helper.rb",
101
+ "test/test_rack_request_proxy.rb",
102
+ "test/test_request_token.rb",
103
+ "test/test_rsa_sha1.rb",
104
+ "test/test_server.rb",
105
+ "test/test_signature.rb",
106
+ "test/test_signature_base.rb",
107
+ "test/test_signature_plain_text.rb",
108
+ "test/test_token.rb",
109
+ "test/test_typhoeus_request_proxy.rb"
110
+ ]
111
+ s.require_paths = ["lib"]
112
+ s.rubyforge_project = %q{oauth}
113
+ s.rubygems_version = %q{1.3.7}
114
+ s.summary = %q{OAuth Core Ruby implementation}
115
+
116
+ if s.respond_to? :specification_version then
117
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
118
+ s.specification_version = 3
119
+
120
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
121
+ s.add_development_dependency(%q<rake>, [">= 0"])
122
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
123
+ s.add_development_dependency(%q<actionpack>, [">= 2.3.5"])
124
+ s.add_development_dependency(%q<rack>, [">= 1.0.0"])
125
+ s.add_development_dependency(%q<mocha>, [">= 0.9.8"])
126
+ s.add_development_dependency(%q<typhoeus>, [">= 0.1.13"])
127
+ s.add_development_dependency(%q<em-http-request>, [">= 0.2.10"])
128
+ s.add_development_dependency(%q<curb>, [">= 0.6.6.0"])
129
+ else
130
+ s.add_dependency(%q<rake>, [">= 0"])
131
+ s.add_dependency(%q<jeweler>, [">= 0"])
132
+ s.add_dependency(%q<actionpack>, [">= 2.3.5"])
133
+ s.add_dependency(%q<rack>, [">= 1.0.0"])
134
+ s.add_dependency(%q<mocha>, [">= 0.9.8"])
135
+ s.add_dependency(%q<typhoeus>, [">= 0.1.13"])
136
+ s.add_dependency(%q<em-http-request>, [">= 0.2.10"])
137
+ s.add_dependency(%q<curb>, [">= 0.6.6.0"])
138
+ end
139
+ else
140
+ s.add_dependency(%q<rake>, [">= 0"])
141
+ s.add_dependency(%q<jeweler>, [">= 0"])
142
+ s.add_dependency(%q<actionpack>, [">= 2.3.5"])
143
+ s.add_dependency(%q<rack>, [">= 1.0.0"])
144
+ s.add_dependency(%q<mocha>, [">= 0.9.8"])
145
+ s.add_dependency(%q<typhoeus>, [">= 0.1.13"])
146
+ s.add_dependency(%q<em-http-request>, [">= 0.2.10"])
147
+ s.add_dependency(%q<curb>, [">= 0.6.6.0"])
148
+ end
149
+ end
150
+
@@ -0,0 +1,34 @@
1
+ desc 'Release the website and new gem version'
2
+ task :deploy => [:check_version, :website, :release] do
3
+ puts "Remember to create SVN tag:"
4
+ puts "svn copy svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/trunk " +
5
+ "svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/tags/REL-#{VERS} "
6
+ puts "Suggested comment:"
7
+ puts "Tagging release #{CHANGES}"
8
+ end
9
+
10
+ desc 'Runs tasks website_generate and install_gem as a local deployment of the gem'
11
+ task :local_deploy => [:website_generate, :install_gem]
12
+
13
+ task :check_version do
14
+ unless ENV['VERSION']
15
+ puts 'Must pass a VERSION=x.y.z release version'
16
+ exit
17
+ end
18
+ unless ENV['VERSION'] == VERS
19
+ puts "Please update your version.rb to match the release version, currently #{VERS}"
20
+ exit
21
+ end
22
+ end
23
+
24
+ desc 'Install the package as a gem, without generating documentation(ri/rdoc)'
25
+ task :install_gem_no_doc => [:clean, :package] do
26
+ sh "#{'sudo ' unless Hoe::WINDOZE }gem install pkg/*.gem --no-rdoc --no-ri"
27
+ end
28
+
29
+ namespace :manifest do
30
+ desc 'Recreate Manifest.txt to include ALL files'
31
+ task :refresh do
32
+ `rake check_manifest | patch -p0 > Manifest.txt`
33
+ end
34
+ end
@@ -0,0 +1,7 @@
1
+ task :ruby_env do
2
+ RUBY_APP = if RUBY_PLATFORM =~ /java/
3
+ "jruby"
4
+ else
5
+ "ruby"
6
+ end unless defined? RUBY_APP
7
+ end
@@ -0,0 +1,17 @@
1
+ desc 'Generate website files'
2
+ task :website_generate => :ruby_env do
3
+ (Dir['website/**/*.txt'] - Dir['website/version*.txt']).each do |txt|
4
+ sh %{ #{RUBY_APP} script/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} }
5
+ end
6
+ end
7
+
8
+ desc 'Upload website files to rubyforge'
9
+ task :website_upload do
10
+ host = "#{rubyforge_username}@rubyforge.org"
11
+ remote_dir = "/var/www/gforge-projects/#{PATH}/"
12
+ local_dir = 'website'
13
+ sh %{rsync -aCv #{local_dir}/ #{host}:#{remote_dir}}
14
+ end
15
+
16
+ desc 'Generate and upload website files'
17
+ task :website => [:website_generate, :website_upload, :publish_docs]
@@ -0,0 +1,19 @@
1
+ require 'test/unit'
2
+ require 'oauth/signature'
3
+ require 'oauth/request_proxy/mock_request'
4
+
5
+
6
+ class OAuthCase < Test::Unit::TestCase
7
+ # avoid whining about a lack of tests
8
+ def run(*args)
9
+ return if @method_name.to_s == "default_test"
10
+ super
11
+ end
12
+
13
+ protected
14
+
15
+ # Creates a fake request
16
+ def request(params={},method='GET',uri="http://photos.example.net/photos")
17
+ OAuth::RequestProxy.proxy({'parameters'=>params,'method'=>method,'uri'=>uri})
18
+ end
19
+ end
@@ -0,0 +1,62 @@
1
+ require File.expand_path('../../../oauth_case', __FILE__)
2
+
3
+ # See http://oauth.net/core/1.0/#anchor14
4
+ #
5
+ #9.1.2. Construct Request URL
6
+ #
7
+ #The Signature Base String includes the request absolute URL, tying the signature to a specific endpoint. The URL used in the Signature Base String MUST include the scheme, authority, and path, and MUST exclude the query and fragment as defined by [RFC3986] section 3.
8
+ #
9
+ #If the absolute request URL is not available to the Service Provider (it is always available to the Consumer), it can be constructed by combining the scheme being used, the HTTP Host header, and the relative HTTP request URL. If the Host header is not available, the Service Provider SHOULD use the host name communicated to the Consumer in the documentation or other means.
10
+ #
11
+ #The Service Provider SHOULD document the form of URL used in the Signature Base String to avoid ambiguity due to URL normalization. Unless specified, URL scheme and authority MUST be lowercase and include the port number; http default port 80 and https default port 443 MUST be excluded.
12
+ #
13
+ #For example, the request:
14
+ #
15
+ # HTTP://Example.com:80/resource?id=123
16
+ #Is included in the Signature Base String as:
17
+ #
18
+ # http://example.com/resource
19
+
20
+
21
+ class ConstructRequestUrlTest < OAuthCase
22
+
23
+ def test_from_spec
24
+ assert_request_url("http://example.com/resource","HTTP://Example.com:80/resource?id=123")
25
+ end
26
+
27
+ def test_simple_url_with_ending_slash
28
+ assert_request_url("http://example.com/","http://example.com/")
29
+ end
30
+
31
+ def test_simple_url_without_ending_slash
32
+ assert_request_url("http://example.com/","http://example.com")
33
+ end
34
+
35
+ def test_of_normalized_http
36
+ assert_request_url("http://example.com/resource","http://example.com/resource")
37
+ end
38
+
39
+ def test_of_https
40
+ assert_request_url("https://example.com/resource","HTTPS://Example.com:443/resource?id=123")
41
+ end
42
+
43
+ def test_of_normalized_https
44
+ assert_request_url("https://example.com/resource","https://example.com/resource")
45
+ end
46
+
47
+ def test_of_http_with_non_standard_port
48
+ assert_request_url("http://example.com:8080/resource","http://example.com:8080/resource")
49
+ end
50
+
51
+ def test_of_https_with_non_standard_port
52
+ assert_request_url("https://example.com:8080/resource","https://example.com:8080/resource")
53
+ end
54
+
55
+ protected
56
+
57
+
58
+ def assert_request_url(expected,given,message=nil)
59
+ assert_equal expected, request({},'GET',given).normalized_uri, message
60
+ end
61
+
62
+ end
@@ -0,0 +1,88 @@
1
+ require File.expand_path('../../../oauth_case', __FILE__)
2
+
3
+ # See http://oauth.net/core/1.0/#anchor14
4
+ #
5
+ # 9.1.1. Normalize Request Parameters
6
+ #
7
+ # The request parameters are collected, sorted and concatenated into a normalized string:
8
+ #
9
+ # Parameters in the OAuth HTTP Authorization header excluding the realm parameter.
10
+ # Parameters in the HTTP POST request body (with a content-type of application/x-www-form-urlencoded).
11
+ # HTTP GET parameters added to the URLs in the query part (as defined by [RFC3986] section 3).
12
+ # The oauth_signature parameter MUST be excluded.
13
+ #
14
+ # The parameters are normalized into a single string as follows:
15
+ #
16
+ # Parameters are sorted by name, using lexicographical byte value ordering.
17
+ # If two or more parameters share the same name, they are sorted by their value. For example:
18
+ #
19
+ # a=1, c=hi%20there, f=25, f=50, f=a, z=p, z=t
20
+ # Parameters are concatenated in their sorted order into a single string. For each parameter,
21
+ # the name is separated from the corresponding value by an ‘=’ character (ASCII code 61), even
22
+ # if the value is empty. Each name-value pair is separated by an ‘&’ character (ASCII code 38). For example:
23
+ # a=1&c=hi%20there&f=25&f=50&f=a&z=p&z=t
24
+ #
25
+
26
+
27
+ class NormalizeRequestParametersTest < OAuthCase
28
+
29
+ def test_parameters_for_signature
30
+ params={'a'=>1, 'c'=>'hi there', 'f'=>'25', 'f'=>'50', 'f'=>'a', 'z'=>'p', 'z'=>'t'}
31
+ assert_equal params,request(params).parameters_for_signature
32
+ end
33
+
34
+
35
+ def test_parameters_for_signature_removes_oauth_signature
36
+ params={'a'=>1, 'c'=>'hi there', 'f'=>'25', 'f'=>'50', 'f'=>'a', 'z'=>'p', 'z'=>'t'}
37
+ assert_equal params,request(params.merge({'oauth_signature'=>'blalbla'})).parameters_for_signature
38
+ end
39
+
40
+ def test_spec_example
41
+ assert_normalized 'a=1&c=hi%20there&f=25&f=50&f=a&z=p&z=t', { 'a' => 1, 'c' => 'hi there', 'f' => ['25', '50', 'a'], 'z' => ['p', 't'] }
42
+ end
43
+
44
+ def test_sorts_parameters_correctly
45
+ # values for 'f' are scrambled
46
+ assert_normalized 'a=1&c=hi%20there&f=5&f=70&f=a&z=p&z=t', { 'a' => 1, 'c' => 'hi there', 'f' => ['a', '70', '5'], 'z' => ['p', 't'] }
47
+ end
48
+
49
+ def test_empty
50
+ assert_normalized "",{}
51
+ end
52
+
53
+
54
+ # These are from the wiki http://wiki.oauth.net/TestCases
55
+ # in the section Normalize Request Parameters
56
+ # Parameters have already been x-www-form-urlencoded (i.e. + = <space>)
57
+ def test_wiki1
58
+ assert_normalized "name=",{"name"=>nil}
59
+ end
60
+
61
+ def test_wiki2
62
+ assert_normalized "a=b",{'a'=>'b'}
63
+ end
64
+
65
+ def test_wiki3
66
+ assert_normalized "a=b&c=d",{'a'=>'b','c'=>'d'}
67
+ end
68
+
69
+ def test_wiki4
70
+ assert_normalized "a=x%20y&a=x%21y",{'a'=>["x!y","x y"]}
71
+
72
+ end
73
+
74
+ def test_wiki5
75
+ assert_normalized "x=a&x%21y=a",{"x!y"=>'a','x'=>'a'}
76
+ end
77
+
78
+ protected
79
+
80
+
81
+ def assert_normalized(expected,params,message=nil)
82
+ assert_equal expected, normalize_request_parameters(params), message
83
+ end
84
+
85
+ def normalize_request_parameters(params={})
86
+ request(params).normalized_parameters
87
+ end
88
+ end
@@ -0,0 +1,86 @@
1
+ require File.expand_path('../../../oauth_case', __FILE__)
2
+
3
+ # See http://oauth.net/core/1.0/#encoding_parameters
4
+ #
5
+ # 5.1. Parameter Encoding
6
+ #
7
+ # All parameter names and values are escaped using the [RFC3986] percent-encoding (%xx) mechanism.
8
+ # Characters not in the unreserved character set ([RFC3986] section 2.3) MUST be encoded. Characters
9
+ # in the unreserved character set MUST NOT be encoded. Hexadecimal characters in encodings MUST be
10
+ # upper case. Text names and values MUST be encoded as UTF-8 octets before percent-encoding them per [RFC3629].
11
+ #
12
+ # unreserved = ALPHA, DIGIT, '-', '.', '_', '~'
13
+ #
14
+
15
+ class ParameterEncodingTest < OAuthCase
16
+ def test_encodings_alpha_num
17
+ assert_encoding 'abcABC123', 'abcABC123'
18
+ end
19
+
20
+ def test_encodings_non_escaped
21
+ assert_encoding '-._~', '-._~'
22
+ end
23
+
24
+ def test_encodings_percent
25
+ assert_encoding '%25', '%'
26
+ end
27
+
28
+ def test_encodings_plus
29
+ assert_encoding '%2B', '+'
30
+ end
31
+
32
+ def test_encodings_space
33
+ assert_encoding '%20', ' '
34
+ end
35
+
36
+ def test_encodings_query_param_symbols
37
+ assert_encoding '%26%3D%2A', '&=*'
38
+ end
39
+
40
+ def test_encodings_unicode_lf
41
+ assert_encoding '%0A', unicode_to_utf8('U+000A')
42
+ end
43
+
44
+ def test_encodings_unicode_space
45
+ assert_encoding '%20', unicode_to_utf8('U+0020')
46
+ end
47
+
48
+ def test_encodings_unicode_007f
49
+ assert_encoding '%7F', unicode_to_utf8('U+007F')
50
+ end
51
+
52
+ def test_encodings_unicode_0080
53
+ assert_encoding '%C2%80', unicode_to_utf8('U+0080')
54
+ end
55
+
56
+ def test_encoding_unicode_2708
57
+ assert_encoding '%E2%9C%88', unicode_to_utf8('U+2708')
58
+ end
59
+
60
+ def test_encodings_unicode_3001
61
+ assert_encoding '%E3%80%81', unicode_to_utf8('U+3001')
62
+ end
63
+
64
+ protected
65
+
66
+ def unicode_to_utf8(unicode)
67
+ return unicode if unicode =~ /\A[[:space:]]*\z/m
68
+
69
+ str = ''
70
+
71
+ unicode.scan(/(U\+(?:[[:digit:][:xdigit:]]{4,5}|10[[:digit:][:xdigit:]]{4})|.)/mu) do
72
+ c = $1
73
+ if c =~ /^U\+/
74
+ str << [c[2..-1].hex].pack('U*')
75
+ else
76
+ str << c
77
+ end
78
+ end
79
+
80
+ str
81
+ end
82
+
83
+ def assert_encoding(expected, given, message = nil)
84
+ assert_equal expected, OAuth::Helper.escape(given), message
85
+ end
86
+ end