diff --git a/lib/simple_oauth/header.rb b/lib/simple_oauth/header.rb index 422c9dd..16aa6e4 100644 --- a/lib/simple_oauth/header.rb +++ b/lib/simple_oauth/header.rb @@ -6,33 +6,43 @@ require 'cgi' module SimpleOAuth class Header ATTRIBUTE_KEYS = [:callback, :consumer_key, :nonce, :signature_method, :timestamp, :token, :verifier, :version] unless defined? ::SimpleOAuth::Header::ATTRIBUTE_KEYS - - def self.default_options - { - :nonce => OpenSSL::Random.random_bytes(16).unpack('H*')[0], - :signature_method => 'HMAC-SHA1', - :timestamp => Time.now.to_i.to_s, - :version => '1.0' - } - end - - def self.encode(value) - uri_parser.escape(value.to_s, /[^a-z0-9\-\.\_\~]/i) - end - - def self.decode(value) - uri_parser.unescape(value.to_s) - end - - def self.parse(header) - header.to_s.sub(/^OAuth\s/, '').split(/,\s*/).inject({}) do |attributes, pair| - match = pair.match(/^(\w+)\=\"([^\"]*)\"$/) - attributes.merge(match[1].sub(/^oauth_/, '').to_sym => decode(match[2])) - end - end - attr_reader :method, :params, :options + class << self + def default_options + { + :nonce => OpenSSL::Random.random_bytes(16).unpack('H*')[0], + :signature_method => 'HMAC-SHA1', + :timestamp => Time.now.to_i.to_s, + :version => '1.0' + } + end + + def parse(header) + header.to_s.sub(/^OAuth\s/, '').split(/,\s*/).inject({}) do |attributes, pair| + match = pair.match(/^(\w+)\=\"([^\"]*)\"$/) + attributes.merge(match[1].sub(/^oauth_/, '').to_sym => decode(match[2])) + end + end + + def escape(value) + uri_parser.escape(value.to_s, /[^a-z0-9\-\.\_\~]/i) + end + alias encode escape + + def unescape(value) + uri_parser.unescape(value.to_s) + end + alias decode unescape + + private + + def uri_parser + @uri_parser ||= URI.const_defined?(:Parser) ? URI::Parser.new : URI + end + + end + def initialize(method, url, params, oauth = {}) @method = method.to_s.upcase @uri = URI.parse(url.to_s) @@ -65,11 +75,7 @@ module SimpleOAuth attributes.merge(:oauth_signature => signature) end - private - - def self.uri_parser - @uri_parser ||= URI.const_defined?(:Parser) ? URI::Parser.new : URI - end + private def normalized_attributes signed_attributes.sort_by{|k,v| k.to_s }.map{|k,v| %(#{k}="#{self.class.encode(v)}") }.join(', ') diff --git a/spec/simple_oauth/header_spec.rb b/spec/simple_oauth/header_spec.rb index ce7070a..466a6e3 100644 --- a/spec/simple_oauth/header_spec.rb +++ b/spec/simple_oauth/header_spec.rb @@ -22,29 +22,29 @@ describe SimpleOAuth::Header do end end - describe ".encode" do - it "encodes (most) non-word characters" do + describe ".escape" do + it "escapes (most) non-word characters" do [' ', '!', '@', '#', '$', '%', '^', '&'].each do |character| - encoded = SimpleOAuth::Header.encode(character) - expect(encoded).not_to eq character - expect(encoded).to eq uri_parser.escape(character, /.*/) + escaped = SimpleOAuth::Header.escape(character) + expect(escaped).not_to eq character + expect(escaped).to eq uri_parser.escape(character, /.*/) end end - it "does not encode - . or ~" do + it "does not escape - . or ~" do ['-', '.', '~'].each do |character| - encoded = SimpleOAuth::Header.encode(character) - expect(encoded).to eq character + escaped = SimpleOAuth::Header.escape(character) + expect(escaped).to eq character end end def self.test_special_characters - it "encodes non-ASCII characters" do - expect(SimpleOAuth::Header.encode('é')).to eq '%C3%A9' + it "escapes non-ASCII characters" do + expect(SimpleOAuth::Header.escape('é')).to eq '%C3%A9' end - it "encodes multibyte characters" do - expect(SimpleOAuth::Header.encode('あ')).to eq '%E3%81%82' + it "escapes multibyte characters" do + expect(SimpleOAuth::Header.escape('あ')).to eq '%E3%81%82' end end @@ -65,7 +65,7 @@ describe SimpleOAuth::Header do end end - describe ".decode" do + describe ".unescape" do pending end @@ -163,7 +163,7 @@ describe SimpleOAuth::Header do expect(normalized_attributes).to eq 'a="4", b="3", c="2", d="1"' end - it "url-encodes its values" do + it "URI encodes its values" do header.stub(:signed_attributes => {1 => '!', 2 => '@', 3 => '#', 4 => '$'}) expect(normalized_attributes).to eq '1="%21", 2="%40", 3="%23", 4="%24"' end @@ -261,7 +261,7 @@ describe SimpleOAuth::Header do expect(secret).to eq 'CONSUMER_SECRET&TOKEN_SECRET' end - it "URL encodes each secret value before combination" do + it "URI encodes each secret value before combination" do header.stub(:options => {:consumer_secret => 'CONSUM#R_SECRET', :token_secret => 'TOKEN_S#CRET'}) expect(secret).to eq 'CONSUM%23R_SECRET&TOKEN_S%23CRET' end @@ -276,7 +276,7 @@ describe SimpleOAuth::Header do expect(signature_base).to eq 'METHOD&URL&NORMALIZED_PARAMS' end - it "URL encodes each value before combination" do + it "URI encodes each value before combination" do header.stub(:method => 'ME#HOD', :url => 'U#L', :normalized_params => 'NORMAL#ZED_PARAMS') expect(signature_base).to eq 'ME%23HOD&U%23L&NORMAL%23ZED_PARAMS' end