oauth 0.2.7 → 0.3.0
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.
- data/History.txt +14 -0
- data/Manifest.txt +19 -3
- data/{README.txt → README.rdoc} +0 -0
- data/Rakefile +34 -4
- data/TODO +14 -0
- data/bin/oauth +5 -0
- data/lib/oauth.rb +3 -3
- data/lib/oauth/cli.rb +130 -0
- data/lib/oauth/client/helper.rb +3 -2
- data/lib/oauth/consumer.rb +1 -1
- data/lib/oauth/helper.rb +3 -0
- data/lib/oauth/oauth_test_helper.rb +26 -0
- data/lib/oauth/request_proxy/action_controller_request.rb +2 -4
- data/lib/oauth/request_proxy/base.rb +31 -0
- data/lib/oauth/request_proxy/jabber_request.rb +42 -0
- data/lib/oauth/request_proxy/mock_request.rb +36 -0
- data/lib/oauth/request_proxy/net_http.rb +0 -2
- data/lib/oauth/request_proxy/rack_request.rb +1 -3
- data/lib/oauth/signature/base.rb +20 -7
- data/lib/oauth/signature/plaintext.rb +1 -1
- data/lib/oauth/token.rb +3 -3
- data/lib/oauth/version.rb +2 -8
- data/oauth.gemspec +43 -0
- data/script/txt2html +1 -1
- data/specs.txt +13 -0
- data/test/cases/oauth_case.rb +19 -0
- data/test/cases/spec/1_0-final/test_construct_request_url.rb +62 -0
- data/test/cases/spec/1_0-final/test_normalize_request_parameters.rb +88 -0
- data/test/cases/spec/1_0-final/test_parameter_encodings.rb +86 -0
- data/test/cases/spec/1_0-final/test_signature_base_strings.rb +77 -0
- data/test/keys/rsa.cert +11 -0
- data/test/keys/rsa.pem +16 -0
- data/test/test_action_controller_request_proxy.rb +2 -1
- data/test/test_consumer.rb +17 -18
- data/test/test_helper.rb +8 -0
- data/test/test_net_http_client.rb +7 -7
- data/test/test_net_http_request_proxy.rb +3 -3
- data/test/test_rack_request_proxy.rb +3 -3
- data/test/test_signature_plain_text.rb +31 -0
- data/website/index.html +1 -1
- metadata +43 -11
- data/config/hoe.rb +0 -71
- data/config/requirements.rb +0 -17
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'oauth/request_proxy/base'
|
2
|
+
|
3
|
+
module OAuth
|
4
|
+
module RequestProxy
|
5
|
+
# RequestProxy for Hashes to facilitate simpler signature creation.
|
6
|
+
# Usage:
|
7
|
+
# request = OAuth::RequestProxy.proxy \
|
8
|
+
# "method" => "iq",
|
9
|
+
# "uri" => [from, to] * "&",
|
10
|
+
# "parameters" => {
|
11
|
+
# "oauth_consumer_key" => oauth_consumer_key,
|
12
|
+
# "oauth_token" => oauth_token,
|
13
|
+
# "oauth_signature_method" => "HMAC-SHA1"
|
14
|
+
# }
|
15
|
+
#
|
16
|
+
# signature = OAuth::Signature.sign \
|
17
|
+
# request,
|
18
|
+
# :consumer_secret => oauth_consumer_secret,
|
19
|
+
# :token_secret => oauth_token_secret,
|
20
|
+
class MockRequest < OAuth::RequestProxy::Base
|
21
|
+
proxies Hash
|
22
|
+
|
23
|
+
def parameters
|
24
|
+
@request["parameters"]
|
25
|
+
end
|
26
|
+
|
27
|
+
def method
|
28
|
+
@request["method"]
|
29
|
+
end
|
30
|
+
|
31
|
+
def uri
|
32
|
+
@request["uri"]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/oauth/signature/base.rb
CHANGED
@@ -24,11 +24,26 @@ module OAuth::Signature
|
|
24
24
|
raise TypeError unless request.kind_of?(OAuth::RequestProxy::Base)
|
25
25
|
@request = request
|
26
26
|
@options = options
|
27
|
+
|
27
28
|
if block_given?
|
28
|
-
|
29
|
+
|
30
|
+
# consumer secret and token secret need to be looked up based on pieces of the request
|
31
|
+
@token_secret, @consumer_secret = yield block.arity == 1 ? request : [token, consumer_key,nonce,request.timestamp]
|
32
|
+
|
29
33
|
else
|
30
|
-
|
31
|
-
|
34
|
+
## consumer secret was determined beforehand
|
35
|
+
|
36
|
+
@consumer_secret = options[:consumer].secret if options[:consumer]
|
37
|
+
|
38
|
+
# presence of :consumer_secret option will override any Consumer that's provided
|
39
|
+
@consumer_secret = options[:consumer_secret] if options[:consumer_secret]
|
40
|
+
|
41
|
+
## token secret was determined beforehand
|
42
|
+
|
43
|
+
@token_secret = options[:token].secret if options[:token]
|
44
|
+
|
45
|
+
# presence of :token_secret option will override any Token that's provided
|
46
|
+
@token_secret = options[:token_secret] if options[:token_secret]
|
32
47
|
end
|
33
48
|
end
|
34
49
|
|
@@ -45,11 +60,9 @@ module OAuth::Signature
|
|
45
60
|
end
|
46
61
|
|
47
62
|
def signature_base_string
|
48
|
-
|
49
|
-
base = [request.method, request.uri, normalized_params]
|
50
|
-
sbs = base.map { |v| escape(v) }.join("&")
|
63
|
+
request.signature_base_string
|
51
64
|
end
|
52
|
-
|
65
|
+
|
53
66
|
private
|
54
67
|
|
55
68
|
def token
|
data/lib/oauth/token.rb
CHANGED
@@ -30,7 +30,7 @@ module OAuth
|
|
30
30
|
class ConsumerToken<Token
|
31
31
|
attr_accessor :consumer
|
32
32
|
|
33
|
-
def initialize(consumer,token,secret)
|
33
|
+
def initialize(consumer,token="",secret="")
|
34
34
|
super token,secret
|
35
35
|
@consumer=consumer
|
36
36
|
end
|
@@ -62,7 +62,7 @@ module OAuth
|
|
62
62
|
|
63
63
|
# exchange for AccessToken on server
|
64
64
|
def get_access_token(options={})
|
65
|
-
response=consumer.token_request(consumer.http_method,consumer.
|
65
|
+
response=consumer.token_request(consumer.http_method,consumer.access_token_url,self,options)
|
66
66
|
OAuth::AccessToken.new(consumer,response[:oauth_token],response[:oauth_token_secret])
|
67
67
|
end
|
68
68
|
end
|
@@ -71,7 +71,7 @@ module OAuth
|
|
71
71
|
class AccessToken<ConsumerToken
|
72
72
|
|
73
73
|
# The less intrusive way. Otherwise, if we are to do it correctly inside consumer,
|
74
|
-
# we need to restructure and touch more methods:
|
74
|
+
# we need to restructure and touch more methods: request(), sign!(), etc.
|
75
75
|
def request(http_method, path, *arguments)
|
76
76
|
request_uri = URI.parse(path)
|
77
77
|
site_uri = consumer.uri
|
data/lib/oauth/version.rb
CHANGED
data/oauth.gemspec
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{oauth}
|
5
|
+
s.version = "0.3.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Pelle Braendgaard", "Blaine Cook", "Larry Halff", "Jesse Clark", "Jon Crosby", "Seth Fitzsimmons"]
|
9
|
+
s.date = %q{2009-01-25}
|
10
|
+
s.default_executable = %q{oauth}
|
11
|
+
s.description = %q{OAuth Core Ruby implementation}
|
12
|
+
s.email = %q{pelleb@gmail.com}
|
13
|
+
s.executables = ["oauth"]
|
14
|
+
s.extra_rdoc_files = ["History.txt", "License.txt", "Manifest.txt", "README.rdoc", "specs.txt", "website/index.txt"]
|
15
|
+
s.files = ["History.txt", "License.txt", "Manifest.txt", "README.rdoc", "Rakefile", "TODO", "bin/oauth", "lib/oauth.rb", "lib/oauth/cli.rb", "lib/oauth/client.rb", "lib/oauth/client/action_controller_request.rb", "lib/oauth/client/helper.rb", "lib/oauth/client/net_http.rb", "lib/oauth/consumer.rb", "lib/oauth/helper.rb", "lib/oauth/oauth_test_helper.rb", "lib/oauth/request_proxy.rb", "lib/oauth/request_proxy/action_controller_request.rb", "lib/oauth/request_proxy/base.rb", "lib/oauth/request_proxy/jabber_request.rb", "lib/oauth/request_proxy/mock_request.rb", "lib/oauth/request_proxy/net_http.rb", "lib/oauth/request_proxy/rack_request.rb", "lib/oauth/server.rb", "lib/oauth/signature.rb", "lib/oauth/signature/base.rb", "lib/oauth/signature/hmac/base.rb", "lib/oauth/signature/hmac/md5.rb", "lib/oauth/signature/hmac/rmd160.rb", "lib/oauth/signature/hmac/sha1.rb", "lib/oauth/signature/hmac/sha2.rb", "lib/oauth/signature/md5.rb", "lib/oauth/signature/plaintext.rb", "lib/oauth/signature/rsa/sha1.rb", "lib/oauth/signature/sha1.rb", "lib/oauth/token.rb", "lib/oauth/version.rb", "oauth.gemspec", "script/destroy", "script/generate", "script/txt2html", "setup.rb", "specs.txt", "tasks/deployment.rake", "tasks/environment.rake", "tasks/website.rake", "test/cases/oauth_case.rb", "test/cases/spec/1_0-final/test_construct_request_url.rb", "test/cases/spec/1_0-final/test_normalize_request_parameters.rb", "test/cases/spec/1_0-final/test_parameter_encodings.rb", "test/cases/spec/1_0-final/test_signature_base_strings.rb", "test/keys/rsa.cert", "test/keys/rsa.pem", "test/test_action_controller_request_proxy.rb", "test/test_consumer.rb", "test/test_helper.rb", "test/test_hmac_sha1.rb", "test/test_net_http_client.rb", "test/test_net_http_request_proxy.rb", "test/test_rack_request_proxy.rb", "test/test_rsa_sha1.rb", "test/test_server.rb", "test/test_signature.rb", "test/test_signature_base.rb", "test/test_signature_plain_text.rb", "test/test_token.rb", "website/index.html", "website/index.txt", "website/javascripts/rounded_corners_lite.inc.js", "website/stylesheets/screen.css", "website/template.rhtml"]
|
16
|
+
s.has_rdoc = true
|
17
|
+
s.homepage = %q{http://oauth.rubyforge.org}
|
18
|
+
s.rdoc_options = ["--main", "README.rdoc"]
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
s.rubyforge_project = %q{oauth}
|
21
|
+
s.rubygems_version = %q{1.3.1}
|
22
|
+
s.summary = %q{OAuth Core Ruby implementation}
|
23
|
+
s.test_files = ["test/cases/spec/1_0-final/test_construct_request_url.rb", "test/cases/spec/1_0-final/test_normalize_request_parameters.rb", "test/cases/spec/1_0-final/test_parameter_encodings.rb", "test/cases/spec/1_0-final/test_signature_base_strings.rb", "test/test_action_controller_request_proxy.rb", "test/test_consumer.rb", "test/test_helper.rb", "test/test_hmac_sha1.rb", "test/test_net_http_client.rb", "test/test_net_http_request_proxy.rb", "test/test_rack_request_proxy.rb", "test/test_rsa_sha1.rb", "test/test_server.rb", "test/test_signature.rb", "test/test_signature_base.rb", "test/test_signature_plain_text.rb", "test/test_token.rb"]
|
24
|
+
|
25
|
+
if s.respond_to? :specification_version then
|
26
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
27
|
+
s.specification_version = 2
|
28
|
+
|
29
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
30
|
+
s.add_runtime_dependency(%q<ruby-hmac>, [">= 0.3.1"])
|
31
|
+
s.add_development_dependency(%q<newgem>, [">= 1.2.3"])
|
32
|
+
s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
|
33
|
+
else
|
34
|
+
s.add_dependency(%q<ruby-hmac>, [">= 0.3.1"])
|
35
|
+
s.add_dependency(%q<newgem>, [">= 1.2.3"])
|
36
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
37
|
+
end
|
38
|
+
else
|
39
|
+
s.add_dependency(%q<ruby-hmac>, [">= 0.3.1"])
|
40
|
+
s.add_dependency(%q<newgem>, [">= 1.2.3"])
|
41
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
42
|
+
end
|
43
|
+
end
|
data/script/txt2html
CHANGED
data/specs.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Problems with Specs:
|
2
|
+
====================
|
3
|
+
|
4
|
+
9.1.1 Normalize Request Parameters
|
5
|
+
|
6
|
+
# escapes out individual parameters. Spec says this should simply order and concatenate them. FIXED
|
7
|
+
# duplicate key names should be sorted by value FIXED in mojodna fork
|
8
|
+
|
9
|
+
9.1.2. Construct Request URL
|
10
|
+
|
11
|
+
# Should normalize using scheme, host and path leaving out other uri parameters. Scheme and host should be lowercase. FIXED
|
12
|
+
|
13
|
+
|
@@ -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.dirname(__FILE__) + '/../../oauth_case'
|
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_http
|
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.dirname(__FILE__) + '/../../oauth_case'
|
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.dirname(__FILE__) + '/../../oauth_case'
|
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
|