oauth 0.3.6 → 0.3.7.pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of oauth might be problematic. Click here for more details.
- data/.gitignore +1 -0
- data/History.txt +16 -0
- data/Manifest.txt +2 -0
- data/README.rdoc +13 -0
- data/Rakefile +27 -27
- data/TODO +1 -0
- data/lib/digest/hmac.rb +104 -0
- data/lib/oauth.rb +5 -1
- data/lib/oauth/client/action_controller_request.rb +1 -1
- data/lib/oauth/client/em_http.rb +94 -0
- data/lib/oauth/client/helper.rb +7 -4
- data/lib/oauth/client/net_http.rb +9 -6
- data/lib/oauth/consumer.rb +45 -25
- data/lib/oauth/core_ext.rb +31 -0
- data/lib/oauth/helper.rb +11 -1
- data/lib/oauth/request_proxy/base.rb +4 -3
- data/lib/oauth/request_proxy/curb_request.rb +55 -0
- data/lib/oauth/request_proxy/em_http_request.rb +67 -0
- data/lib/oauth/request_proxy/net_http.rb +9 -6
- data/lib/oauth/request_proxy/typhoeus_request.rb +53 -0
- data/lib/oauth/signature.rb +4 -1
- data/lib/oauth/signature/base.rb +9 -3
- data/lib/oauth/signature/hmac/base.rb +5 -2
- data/lib/oauth/signature/hmac/md5.rb +1 -2
- data/lib/oauth/signature/hmac/rmd160.rb +1 -2
- data/lib/oauth/signature/hmac/sha1.rb +2 -3
- data/lib/oauth/signature/hmac/sha2.rb +1 -2
- data/lib/oauth/signature/plaintext.rb +2 -2
- data/lib/oauth/version.rb +1 -1
- data/oauth.gemspec +157 -27
- data/test/integration/consumer_test.rb +304 -0
- data/test/test_action_controller_request_proxy.rb +4 -1
- data/test/test_consumer.rb +51 -254
- data/test/test_curb_request_proxy.rb +69 -0
- data/test/test_em_http_client.rb +74 -0
- data/test/test_em_http_request_proxy.rb +107 -0
- data/test/test_helper.rb +15 -9
- data/test/test_net_http_client.rb +59 -5
- data/test/test_net_http_request_proxy.rb +1 -1
- data/test/test_signature.rb +6 -3
- data/test/test_typhoeus_request_proxy.rb +73 -0
- data/website/index.html +2 -2
- metadata +43 -25
    
        data/.gitignore
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            pkg/*
         | 
    
        data/History.txt
    CHANGED
    
    | @@ -1,3 +1,19 @@ | |
| 1 | 
            +
            == 0.3.7
         | 
| 2 | 
            +
            * Better marshalling implementation (Yoan Blanc)
         | 
| 3 | 
            +
            * Added optional block to OAuth::Consumer.get_*_token (Neill Pearman)
         | 
| 4 | 
            +
            * Exclude `oauth_callback` with :exclude_callback (Neill Pearman)
         | 
| 5 | 
            +
            * Strip extraneous spaces and line breaks from access_token responses
         | 
| 6 | 
            +
              (observed in the wild with Yahoo!'s OAuth+OpenID hybrid) (Eric Hartmann)
         | 
| 7 | 
            +
            * Stop double-escaping PLAINTEXT signatures (Jimmy Zimmerman)
         | 
| 8 | 
            +
            * OAuth::Client::Helper won't override the specified `oauth_version`
         | 
| 9 | 
            +
              (Philip Kromer)
         | 
| 10 | 
            +
            * Support for Ruby 1.9 (Aaron Quint, Corey Donahoe, et al)
         | 
| 11 | 
            +
            * Fixed an encoding / multibyte issue (成田 一生)
         | 
| 12 | 
            +
            * Replaced hoe with Jeweler (Aaron Quint)
         | 
| 13 | 
            +
            * Support for Typhoeus (Bill Kocik)
         | 
| 14 | 
            +
            * Support for em-http (EventMachine) (Darcy Laycock)
         | 
| 15 | 
            +
            * Support for curb (André Luis Leal Cardoso Junior)
         | 
| 16 | 
            +
             | 
| 1 17 | 
             
            == 0.3.6 2009-09-14
         | 
| 2 18 |  | 
| 3 19 | 
             
            * Added -B CLI option to use the :body authentication scheme (Seth)
         | 
    
        data/Manifest.txt
    CHANGED
    
    | @@ -13,6 +13,7 @@ lib/oauth/client.rb | |
| 13 13 | 
             
            lib/oauth/client/action_controller_request.rb
         | 
| 14 14 | 
             
            lib/oauth/client/helper.rb
         | 
| 15 15 | 
             
            lib/oauth/client/net_http.rb
         | 
| 16 | 
            +
            lib/oauth/client/em_http.rb
         | 
| 16 17 | 
             
            lib/oauth/consumer.rb
         | 
| 17 18 | 
             
            lib/oauth/errors.rb
         | 
| 18 19 | 
             
            lib/oauth/errors/error.rb
         | 
| @@ -27,6 +28,7 @@ lib/oauth/request_proxy/jabber_request.rb | |
| 27 28 | 
             
            lib/oauth/request_proxy/mock_request.rb
         | 
| 28 29 | 
             
            lib/oauth/request_proxy/net_http.rb
         | 
| 29 30 | 
             
            lib/oauth/request_proxy/rack_request.rb
         | 
| 31 | 
            +
            lib/oauth/request_proxy/em_http_request.rb
         | 
| 30 32 | 
             
            lib/oauth/server.rb
         | 
| 31 33 | 
             
            lib/oauth/signature.rb
         | 
| 32 34 | 
             
            lib/oauth/signature/base.rb
         | 
    
        data/README.rdoc
    CHANGED
    
    | @@ -37,8 +37,21 @@ When user returns create an access_token | |
| 37 37 | 
             
              @access_token = @request_token.get_access_token
         | 
| 38 38 | 
             
              @photos = @access_token.get('/photos.xml')
         | 
| 39 39 |  | 
| 40 | 
            +
            Now that you have an access token, you can use Typhoeus to interact with the OAuth provider if you choose.
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              oauth_params = {:consumer => oauth_consumer, :token => access_token}
         | 
| 43 | 
            +
              hydra = Typhoeus::Hydra.new
         | 
| 44 | 
            +
              req = Typhoeus::Request.new(uri, options) 
         | 
| 45 | 
            +
              oauth_helper = OAuth::Client::Helper.new(req, oauth_params.merge(:request_uri => uri))
         | 
| 46 | 
            +
              req.headers.merge!({"Authorization" => oauth_helper.header}) # Signs the request
         | 
| 47 | 
            +
              hydra.queue(req)
         | 
| 48 | 
            +
              hydra.run
         | 
| 49 | 
            +
              @response = req.response
         | 
| 50 | 
            +
             | 
| 40 51 | 
             
            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 .
         | 
| 41 52 |  | 
| 53 | 
            +
            If you wish to use em-http-request, you can find an example "in the official em-http-request repository":http://github.com/igrigorik/em-http-request/blob/master/examples/oauth-tweet.rb
         | 
| 54 | 
            +
             | 
| 42 55 | 
             
            Finally be sure to check out the OAuth RDoc Manual http://oauth.rubyforge.org/rdoc/ .
         | 
| 43 56 |  | 
| 44 57 | 
             
            == Documentation Wiki
         | 
    
        data/Rakefile
    CHANGED
    
    | @@ -1,36 +1,36 @@ | |
| 1 | 
            -
            %w[rubygems rake rake/clean fileutils | 
| 1 | 
            +
            %w[rubygems rake rake/clean rake/testtask fileutils].each { |f| require f }
         | 
| 2 2 | 
             
            $LOAD_PATH << File.dirname(__FILE__) + '/lib'
         | 
| 3 3 | 
             
            require 'oauth'
         | 
| 4 4 | 
             
            require 'oauth/version'
         | 
| 5 5 |  | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
                [ | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
                 | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 6 | 
            +
            begin
         | 
| 7 | 
            +
              require 'jeweler'
         | 
| 8 | 
            +
              Jeweler::Tasks.new do |s|
         | 
| 9 | 
            +
                s.name = %q{oauth}
         | 
| 10 | 
            +
                s.version = OAuth::VERSION
         | 
| 11 | 
            +
                s.date = %q{2009-08-10}
         | 
| 12 | 
            +
                s.authors = ["Pelle Braendgaard", "Blaine Cook", "Larry Halff", "Jesse Clark", "Jon Crosby", "Seth Fitzsimmons", "Matt Sanford", "Aaron Quint"]
         | 
| 13 | 
            +
                s.email = "oauth-ruby@googlegroups.com"
         | 
| 14 | 
            +
                s.description = "OAuth Core Ruby implementation"
         | 
| 15 | 
            +
                s.summary = s.description
         | 
| 16 | 
            +
                s.rubyforge_project = %q{oauth}
         | 
| 17 | 
            +
                s.add_development_dependency(%q<actionpack>, [">= 2.2.0"])
         | 
| 18 | 
            +
                s.add_development_dependency(%q<rack>, [">= 1.0.0"])
         | 
| 19 | 
            +
                s.add_development_dependency(%q<mocha>, [">= 0.9.8"])
         | 
| 20 | 
            +
                s.add_development_dependency(%q<typhoeus>, [">= 0.1.13"])
         | 
| 21 | 
            +
                s.add_development_dependency(%q<em-http-request>)
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
              Jeweler::GemcutterTasks.new
         | 
| 24 | 
            +
            rescue LoadError
         | 
| 25 | 
            +
              puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
         | 
| 26 | 
            +
            end
         | 
| 25 27 |  | 
| 26 | 
            -
             | 
| 27 | 
            -
               | 
| 28 | 
            -
               | 
| 29 | 
            -
               | 
| 28 | 
            +
            Rake::TestTask.new do |t|
         | 
| 29 | 
            +
              t.libs << "test"
         | 
| 30 | 
            +
              t.test_files = FileList['test/*test*.rb']
         | 
| 31 | 
            +
              t.verbose = true
         | 
| 30 32 | 
             
            end
         | 
| 31 33 |  | 
| 32 | 
            -
            require 'newgem/tasks' # load /tasks/*.rake
         | 
| 33 34 | 
             
            Dir['tasks/**/*.rake'].each { |t| load t }
         | 
| 34 35 |  | 
| 35 | 
            -
             | 
| 36 | 
            -
            # task :default => [:spec, :features]
         | 
| 36 | 
            +
            task :default => :test
         | 
    
        data/TODO
    CHANGED
    
    
    
        data/lib/digest/hmac.rb
    ADDED
    
    | @@ -0,0 +1,104 @@ | |
| 1 | 
            +
            # = digest/hmac.rb
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # An implementation of HMAC keyed-hashing algorithm
         | 
| 4 | 
            +
            #
         | 
| 5 | 
            +
            # == Overview 
         | 
| 6 | 
            +
            # 
         | 
| 7 | 
            +
            # This library adds a method named hmac() to Digest classes, which
         | 
| 8 | 
            +
            # creates a Digest class for calculating HMAC digests.
         | 
| 9 | 
            +
            #
         | 
| 10 | 
            +
            # == Examples
         | 
| 11 | 
            +
            #
         | 
| 12 | 
            +
            #   require 'digest/hmac'
         | 
| 13 | 
            +
            #
         | 
| 14 | 
            +
            #   # one-liner example
         | 
| 15 | 
            +
            #   puts Digest::HMAC.hexdigest("data", "hash key", Digest::SHA1)
         | 
| 16 | 
            +
            #
         | 
| 17 | 
            +
            #   # rather longer one
         | 
| 18 | 
            +
            #   hmac = Digest::HMAC.new("foo", Digest::RMD160)
         | 
| 19 | 
            +
            #
         | 
| 20 | 
            +
            #   buf = ""
         | 
| 21 | 
            +
            #   while stream.read(16384, buf)
         | 
| 22 | 
            +
            #     hmac.update(buf)
         | 
| 23 | 
            +
            #   end
         | 
| 24 | 
            +
            #
         | 
| 25 | 
            +
            #   puts hmac.bubblebabble
         | 
| 26 | 
            +
            #
         | 
| 27 | 
            +
            # == License
         | 
| 28 | 
            +
            #
         | 
| 29 | 
            +
            # Copyright (c) 2006 Akinori MUSHA <knu@iDaemons.org>
         | 
| 30 | 
            +
            #
         | 
| 31 | 
            +
            # Documentation by Akinori MUSHA
         | 
| 32 | 
            +
            #
         | 
| 33 | 
            +
            # All rights reserved.  You can redistribute and/or modify it under
         | 
| 34 | 
            +
            # the same terms as Ruby.
         | 
| 35 | 
            +
            #
         | 
| 36 | 
            +
            #   $Id: hmac.rb 14881 2008-01-04 07:26:14Z akr $
         | 
| 37 | 
            +
            #
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            require 'digest'
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            unless defined?(Digest::HMAC)
         | 
| 42 | 
            +
              module Digest
         | 
| 43 | 
            +
                class HMAC < Digest::Class
         | 
| 44 | 
            +
                  def initialize(key, digester)
         | 
| 45 | 
            +
                    @md = digester.new
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                    block_len = @md.block_length
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    if key.bytesize > block_len
         | 
| 50 | 
            +
                      key = @md.digest(key)
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                    ipad = Array.new(block_len).fill(0x36)
         | 
| 54 | 
            +
                    opad = Array.new(block_len).fill(0x5c)
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    key.bytes.each_with_index { |c, i|
         | 
| 57 | 
            +
                      ipad[i] ^= c
         | 
| 58 | 
            +
                      opad[i] ^= c
         | 
| 59 | 
            +
                    }
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    @key = key.freeze
         | 
| 62 | 
            +
                    @ipad = ipad.inject('') { |s, c| s << c.chr }.freeze
         | 
| 63 | 
            +
                    @opad = opad.inject('') { |s, c| s << c.chr }.freeze
         | 
| 64 | 
            +
                    @md.update(@ipad)
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  def initialize_copy(other)
         | 
| 68 | 
            +
                    @md = other.instance_eval { @md.clone }
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  def update(text)
         | 
| 72 | 
            +
                    @md.update(text)
         | 
| 73 | 
            +
                    self
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
                  alias << update
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  def reset
         | 
| 78 | 
            +
                    @md.reset
         | 
| 79 | 
            +
                    @md.update(@ipad)
         | 
| 80 | 
            +
                    self
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                  def finish
         | 
| 84 | 
            +
                    d = @md.digest!
         | 
| 85 | 
            +
                    @md.update(@opad)
         | 
| 86 | 
            +
                    @md.update(d)
         | 
| 87 | 
            +
                    @md.digest!
         | 
| 88 | 
            +
                  end
         | 
| 89 | 
            +
                  private :finish
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                  def digest_length
         | 
| 92 | 
            +
                    @md.digest_length
         | 
| 93 | 
            +
                  end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                  def block_length
         | 
| 96 | 
            +
                    @md.block_length
         | 
| 97 | 
            +
                  end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                  def inspect
         | 
| 100 | 
            +
                    sprintf('#<%s: key=%s, digest=%s>', self.class.name, @key.inspect, @md.inspect.sub(/^\#<(.*)>$/) { $1 });
         | 
| 101 | 
            +
                  end
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
              end
         | 
| 104 | 
            +
            end
         | 
    
        data/lib/oauth.rb
    CHANGED
    
    | @@ -1,4 +1,8 @@ | |
| 1 | 
            +
            $LOAD_PATH << File.dirname(__FILE__) unless $LOAD_PATH.include?(File.dirname(__FILE__))
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            require 'oauth/oauth'
         | 
| 4 | 
            +
            require 'oauth/core_ext'
         | 
| 5 | 
            +
             | 
| 2 6 | 
             
            require 'oauth/client/helper'
         | 
| 3 7 | 
             
            require 'oauth/signature/hmac/sha1'
         | 
| 4 | 
            -
            require 'oauth/request_proxy/mock_request'
         | 
| 8 | 
            +
            require 'oauth/request_proxy/mock_request'
         | 
| @@ -0,0 +1,94 @@ | |
| 1 | 
            +
            require 'em-http'
         | 
| 2 | 
            +
            require 'oauth/helper'
         | 
| 3 | 
            +
            require 'oauth/client/helper'
         | 
| 4 | 
            +
            require 'oauth/request_proxy/em_http_request'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # Extensions for em-http so that we can use consumer.sign! with an EventMachine::HttpClient
         | 
| 7 | 
            +
            # instance. This is purely syntactic sugar.
         | 
| 8 | 
            +
            class EventMachine::HttpClient
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              attr_reader :oauth_helper
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              # Add the OAuth information to an HTTP request. Depending on the <tt>options[:scheme]</tt> setting
         | 
| 13 | 
            +
              # this may add a header, additional query string parameters, or additional POST body parameters.
         | 
| 14 | 
            +
              # The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
         | 
| 15 | 
            +
              # header.
         | 
| 16 | 
            +
              # 
         | 
| 17 | 
            +
              # * http - Configured Net::HTTP instance, ignored in this scenario except for getting host.
         | 
| 18 | 
            +
              # * consumer - OAuth::Consumer instance
         | 
| 19 | 
            +
              # * token - OAuth::Token instance
         | 
| 20 | 
            +
              # * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
         | 
| 21 | 
            +
              #   +signature_method+, +nonce+, +timestamp+)
         | 
| 22 | 
            +
              #
         | 
| 23 | 
            +
              # This method also modifies the <tt>User-Agent</tt> header to add the OAuth gem version.
         | 
| 24 | 
            +
              #
         | 
| 25 | 
            +
              # See Also: {OAuth core spec version 1.0, section 5.4.1}[http://oauth.net/core/1.0#rfc.section.5.4.1]
         | 
| 26 | 
            +
              def oauth!(http, consumer = nil, token = nil, options = {})
         | 
| 27 | 
            +
                options = { :request_uri      => normalized_oauth_uri(http),
         | 
| 28 | 
            +
                            :consumer         => consumer,
         | 
| 29 | 
            +
                            :token            => token,
         | 
| 30 | 
            +
                            :scheme           => 'header',
         | 
| 31 | 
            +
                            :signature_method => nil,
         | 
| 32 | 
            +
                            :nonce            => nil,
         | 
| 33 | 
            +
                            :timestamp        => nil }.merge(options)
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                @oauth_helper = OAuth::Client::Helper.new(self, options)
         | 
| 36 | 
            +
                self.__send__(:"set_oauth_#{options[:scheme]}")
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
              # Create a string suitable for signing for an HTTP request. This process involves parameter
         | 
| 40 | 
            +
              # normalization as specified in the OAuth specification. The exact normalization also depends
         | 
| 41 | 
            +
              # on the <tt>options[:scheme]</tt> being used so this must match what will be used for the request
         | 
| 42 | 
            +
              # itself. The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
         | 
| 43 | 
            +
              # header.
         | 
| 44 | 
            +
              # 
         | 
| 45 | 
            +
              # * http - Configured Net::HTTP instance
         | 
| 46 | 
            +
              # * consumer - OAuth::Consumer instance
         | 
| 47 | 
            +
              # * token - OAuth::Token instance
         | 
| 48 | 
            +
              # * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
         | 
| 49 | 
            +
              #   +signature_method+, +nonce+, +timestamp+)
         | 
| 50 | 
            +
              # 
         | 
| 51 | 
            +
              # See Also: {OAuth core spec version 1.0, section 9.1.1}[http://oauth.net/core/1.0#rfc.section.9.1.1]
         | 
| 52 | 
            +
              def signature_base_string(http, consumer = nil, token = nil, options = {})
         | 
| 53 | 
            +
                options = { :request_uri      => normalized_oauth_uri(http),
         | 
| 54 | 
            +
                            :consumer         => consumer,
         | 
| 55 | 
            +
                            :token            => token,
         | 
| 56 | 
            +
                            :scheme           => 'header',
         | 
| 57 | 
            +
                            :signature_method => nil,
         | 
| 58 | 
            +
                            :nonce            => nil,
         | 
| 59 | 
            +
                            :timestamp        => nil }.merge(options)
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                OAuth::Client::Helper.new(self, options).signature_base_string
         | 
| 62 | 
            +
              end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
              protected
         | 
| 65 | 
            +
             | 
| 66 | 
            +
              # Since we expect to get the host etc details from the http instance (...),
         | 
| 67 | 
            +
              # we create a fake url here. Surely this is a horrible, horrible idea?
         | 
| 68 | 
            +
              def normalized_oauth_uri(http)
         | 
| 69 | 
            +
                uri = URI.parse(normalize_uri.path)
         | 
| 70 | 
            +
                uri.host = http.address
         | 
| 71 | 
            +
                uri.port = http.port
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                if http.respond_to?(:use_ssl?) && http.use_ssl?
         | 
| 74 | 
            +
                  uri.scheme = "https"
         | 
| 75 | 
            +
                else
         | 
| 76 | 
            +
                  uri.scheme = "http"
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
                uri.to_s
         | 
| 79 | 
            +
              end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
              def set_oauth_header
         | 
| 82 | 
            +
                headers = (self.options[:head] ||= {})
         | 
| 83 | 
            +
                headers['Authorization'] = @oauth_helper.header
         | 
| 84 | 
            +
              end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
              def set_oauth_body
         | 
| 87 | 
            +
                raise NotImplementedError, 'please use the set_oauth_header method instead'
         | 
| 88 | 
            +
              end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
              def set_oauth_query_string
         | 
| 91 | 
            +
                raise NotImplementedError, 'please use the set_oauth_header method instead'
         | 
| 92 | 
            +
              end
         | 
| 93 | 
            +
              
         | 
| 94 | 
            +
            end
         | 
    
        data/lib/oauth/client/helper.rb
    CHANGED
    
    | @@ -36,14 +36,16 @@ module OAuth::Client | |
| 36 36 | 
             
                    'oauth_timestamp'        => timestamp,
         | 
| 37 37 | 
             
                    'oauth_nonce'            => nonce,
         | 
| 38 38 | 
             
                    'oauth_verifier'         => options[:oauth_verifier],
         | 
| 39 | 
            -
                    'oauth_version'          => '1.0'
         | 
| 39 | 
            +
                    'oauth_version'          => (options[:oauth_version] || '1.0')
         | 
| 40 40 | 
             
                  }.reject { |k,v| v.to_s == "" }
         | 
| 41 41 | 
             
                end
         | 
| 42 42 |  | 
| 43 43 | 
             
                def signature(extra_options = {})
         | 
| 44 44 | 
             
                  OAuth::Signature.sign(@request, { :uri      => options[:request_uri],
         | 
| 45 45 | 
             
                                                    :consumer => options[:consumer],
         | 
| 46 | 
            -
                                                    :token    => options[:token] | 
| 46 | 
            +
                                                    :token    => options[:token],
         | 
| 47 | 
            +
                                                    :unsigned_parameters => options[:unsigned_parameters]
         | 
| 48 | 
            +
                  }.merge(extra_options) )
         | 
| 47 49 | 
             
                end
         | 
| 48 50 |  | 
| 49 51 | 
             
                def signature_base_string(extra_options = {})
         | 
| @@ -55,7 +57,8 @@ module OAuth::Client | |
| 55 57 |  | 
| 56 58 | 
             
                def amend_user_agent_header(headers)
         | 
| 57 59 | 
             
                  @oauth_ua_string ||= "OAuth gem v#{OAuth::VERSION}"
         | 
| 58 | 
            -
                   | 
| 60 | 
            +
                  # Net::HTTP in 1.9 appends Ruby
         | 
| 61 | 
            +
                  if headers['User-Agent'] && headers['User-Agent'] != 'Ruby' 
         | 
| 59 62 | 
             
                    headers['User-Agent'] += " (#{@oauth_ua_string})"
         | 
| 60 63 | 
             
                  else
         | 
| 61 64 | 
             
                    headers['User-Agent'] = @oauth_ua_string
         | 
| @@ -66,7 +69,7 @@ module OAuth::Client | |
| 66 69 | 
             
                  parameters = oauth_parameters
         | 
| 67 70 | 
             
                  parameters.merge!('oauth_signature' => signature(options.merge(:parameters => parameters)))
         | 
| 68 71 |  | 
| 69 | 
            -
                  header_params_str = parameters.map { |k,v| "#{k}=\"#{escape(v)}\"" }.join(', ')
         | 
| 72 | 
            +
                  header_params_str = parameters.sort.map { |k,v| "#{k}=\"#{escape(v)}\"" }.join(', ')
         | 
| 70 73 |  | 
| 71 74 | 
             
                  realm = "realm=\"#{options[:realm]}\", " if options[:realm]
         | 
| 72 75 | 
             
                  "OAuth #{realm}#{header_params_str}"
         | 
| @@ -80,18 +80,21 @@ private | |
| 80 80 | 
             
                self['Authorization'] = @oauth_helper.header
         | 
| 81 81 | 
             
              end
         | 
| 82 82 |  | 
| 83 | 
            -
              # FIXME: if you're using a POST body and query string parameters,  | 
| 84 | 
            -
              #  | 
| 85 | 
            -
              #  | 
| 83 | 
            +
              # FIXME: if you're using a POST body and query string parameters, this method
         | 
| 84 | 
            +
              # will move query string parameters into the body unexpectedly. This may
         | 
| 85 | 
            +
              # cause problems with non-x-www-form-urlencoded bodies submitted to URLs
         | 
| 86 | 
            +
              # containing query string params. If duplicate parameters are present in both
         | 
| 87 | 
            +
              # places, all instances should be included when calculating the signature
         | 
| 88 | 
            +
              # base string.
         | 
| 89 | 
            +
             | 
| 86 90 | 
             
              def set_oauth_body
         | 
| 87 | 
            -
                self.set_form_data(@oauth_helper.parameters_with_oauth)
         | 
| 91 | 
            +
                self.set_form_data(@oauth_helper.stringify_keys(@oauth_helper.parameters_with_oauth))
         | 
| 88 92 | 
             
                params_with_sig = @oauth_helper.parameters.merge(:oauth_signature => @oauth_helper.signature)
         | 
| 89 | 
            -
                self.set_form_data(params_with_sig)
         | 
| 93 | 
            +
                self.set_form_data(@oauth_helper.stringify_keys(params_with_sig))
         | 
| 90 94 | 
             
              end
         | 
| 91 95 |  | 
| 92 96 | 
             
              def set_oauth_query_string
         | 
| 93 97 | 
             
                oauth_params_str = @oauth_helper.oauth_parameters.map { |k,v| [escape(k), escape(v)] * "=" }.join("&")
         | 
| 94 | 
            -
             | 
| 95 98 | 
             
                uri = URI.parse(path)
         | 
| 96 99 | 
             
                if uri.query.to_s == ""
         | 
| 97 100 | 
             
                  uri.query = oauth_params_str
         | 
    
        data/lib/oauth/consumer.rb
    CHANGED
    
    | @@ -3,6 +3,7 @@ require 'net/https' | |
| 3 3 | 
             
            require 'oauth/oauth'
         | 
| 4 4 | 
             
            require 'oauth/client/net_http'
         | 
| 5 5 | 
             
            require 'oauth/errors'
         | 
| 6 | 
            +
            require 'cgi'
         | 
| 6 7 |  | 
| 7 8 | 
             
            module OAuth
         | 
| 8 9 | 
             
              class Consumer
         | 
| @@ -75,9 +76,9 @@ module OAuth | |
| 75 76 | 
             
                  @secret = consumer_secret
         | 
| 76 77 |  | 
| 77 78 | 
             
                  # ensure that keys are symbols
         | 
| 78 | 
            -
                  @options = @@default_options.merge(options.inject({}) { | | 
| 79 | 
            -
                     | 
| 80 | 
            -
                     | 
| 79 | 
            +
                  @options = @@default_options.merge(options.inject({}) { |opts, (key, value)|
         | 
| 80 | 
            +
                    opts[key.to_sym] = value
         | 
| 81 | 
            +
                    opts
         | 
| 81 82 | 
             
                  })
         | 
| 82 83 | 
             
                end
         | 
| 83 84 |  | 
| @@ -101,8 +102,8 @@ module OAuth | |
| 101 102 | 
             
                  end
         | 
| 102 103 | 
             
                end
         | 
| 103 104 |  | 
| 104 | 
            -
                def get_access_token(request_token, request_options = {}, *arguments)
         | 
| 105 | 
            -
                  response = token_request(http_method, (access_token_url? ? access_token_url : access_token_path), request_token, request_options, *arguments)
         | 
| 105 | 
            +
                def get_access_token(request_token, request_options = {}, *arguments, &block)
         | 
| 106 | 
            +
                  response = token_request(http_method, (access_token_url? ? access_token_url : access_token_path), request_token, request_options, *arguments, &block)
         | 
| 106 107 | 
             
                  OAuth::AccessToken.from_hash(self, response)
         | 
| 107 108 | 
             
                end
         | 
| 108 109 |  | 
| @@ -120,12 +121,20 @@ module OAuth | |
| 120 121 | 
             
                #  @request_token = @consumer.get_request_token({}, :foo => "bar")
         | 
| 121 122 | 
             
                #
         | 
| 122 123 | 
             
                # TODO oauth_callback should be a mandatory parameter
         | 
| 123 | 
            -
                def get_request_token(request_options = {}, *arguments)
         | 
| 124 | 
            +
                def get_request_token(request_options = {}, *arguments, &block)
         | 
| 124 125 | 
             
                  # if oauth_callback wasn't provided, it is assumed that oauth_verifiers
         | 
| 125 126 | 
             
                  # will be exchanged out of band
         | 
| 126 | 
            -
                  request_options[:oauth_callback] ||= OAuth::OUT_OF_BAND
         | 
| 127 | 
            -
             | 
| 128 | 
            -
                   | 
| 127 | 
            +
                  request_options[:oauth_callback] ||= OAuth::OUT_OF_BAND unless request_options[:exclude_callback]
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                  if block_given?
         | 
| 130 | 
            +
                    response = token_request(http_method,
         | 
| 131 | 
            +
                                             (request_token_url? ? request_token_url : request_token_path),
         | 
| 132 | 
            +
                                             nil,
         | 
| 133 | 
            +
                                             request_options,
         | 
| 134 | 
            +
                                             *arguments, &block)
         | 
| 135 | 
            +
                  else
         | 
| 136 | 
            +
                    response = token_request(http_method, (request_token_url? ? request_token_url : request_token_path), nil, request_options, *arguments)
         | 
| 137 | 
            +
                  end
         | 
| 129 138 | 
             
                  OAuth::RequestToken.from_hash(self, response)
         | 
| 130 139 | 
             
                end
         | 
| 131 140 |  | 
| @@ -146,13 +155,16 @@ module OAuth | |
| 146 155 | 
             
                    path = "#{_uri.path}#{_uri.query ? "?#{_uri.query}" : ""}"
         | 
| 147 156 | 
             
                  end
         | 
| 148 157 |  | 
| 149 | 
            -
                   | 
| 158 | 
            +
                  # override the request with your own, this is useful for file uploads which Net::HTTP does not do
         | 
| 159 | 
            +
                  req = create_signed_request(http_method, path, token, request_options, *arguments)
         | 
| 160 | 
            +
                  return nil if block_given? and yield(req) == :done
         | 
| 161 | 
            +
                  rsp = http.request(req)
         | 
| 150 162 |  | 
| 151 163 | 
             
                  # check for an error reported by the Problem Reporting extension
         | 
| 152 164 | 
             
                  # (http://wiki.oauth.net/ProblemReporting)
         | 
| 153 165 | 
             
                  # note: a 200 may actually be an error; check for an oauth_problem key to be sure
         | 
| 154 166 | 
             
                  if !(headers = rsp.to_hash["www-authenticate"]).nil? &&
         | 
| 155 | 
            -
                    (h = headers.select { | | 
| 167 | 
            +
                    (h = headers.select { |hdr| hdr =~ /^OAuth / }).any? &&
         | 
| 156 168 | 
             
                    h.first =~ /oauth_problem/
         | 
| 157 169 |  | 
| 158 170 | 
             
                    # puts "Header: #{h.first}"
         | 
| @@ -181,17 +193,20 @@ module OAuth | |
| 181 193 | 
             
                # Creates a request and parses the result as url_encoded. This is used internally for the RequestToken and AccessToken requests.
         | 
| 182 194 | 
             
                def token_request(http_method, path, token = nil, request_options = {}, *arguments)
         | 
| 183 195 | 
             
                  response = request(http_method, path, token, request_options, *arguments)
         | 
| 184 | 
            -
             | 
| 185 196 | 
             
                  case response.code.to_i
         | 
| 186 197 |  | 
| 187 198 | 
             
                  when (200..299)
         | 
| 188 | 
            -
                     | 
| 189 | 
            -
             | 
| 190 | 
            -
                     | 
| 191 | 
            -
             | 
| 192 | 
            -
                       | 
| 193 | 
            -
                       | 
| 194 | 
            -
                      h
         | 
| 199 | 
            +
                    if block_given?
         | 
| 200 | 
            +
                      yield response.body
         | 
| 201 | 
            +
                    else
         | 
| 202 | 
            +
                      # symbolize keys
         | 
| 203 | 
            +
                      # TODO this could be considered unexpected behavior; symbols or not?
         | 
| 204 | 
            +
                      # TODO this also drops subsequent values from multi-valued keys
         | 
| 205 | 
            +
                      CGI.parse(response.body).inject({}) do |h,(k,v)|
         | 
| 206 | 
            +
                        h[k.strip.to_sym] = v.first
         | 
| 207 | 
            +
                        h[k.strip]        = v.first
         | 
| 208 | 
            +
                        h
         | 
| 209 | 
            +
                      end
         | 
| 195 210 | 
             
                    end
         | 
| 196 211 | 
             
                  when (300..399)
         | 
| 197 212 | 
             
                    # this is a redirect
         | 
| @@ -298,7 +313,6 @@ module OAuth | |
| 298 313 |  | 
| 299 314 | 
             
                  if [:post, :put].include?(http_method)
         | 
| 300 315 | 
             
                    data = arguments.shift
         | 
| 301 | 
            -
                    data.reject! { |k,v| v.nil? } if data.is_a?(Hash)
         | 
| 302 316 | 
             
                  end
         | 
| 303 317 |  | 
| 304 318 | 
             
                  headers = arguments.first.is_a?(Hash) ? arguments.shift : {}
         | 
| @@ -321,7 +335,9 @@ module OAuth | |
| 321 335 | 
             
                  end
         | 
| 322 336 |  | 
| 323 337 | 
             
                  if data.is_a?(Hash)
         | 
| 324 | 
            -
                     | 
| 338 | 
            +
                    form_data = {}
         | 
| 339 | 
            +
                    data.each {|k,v| form_data[k.to_s] = v if !v.nil?} 
         | 
| 340 | 
            +
                    request.set_form_data(form_data)
         | 
| 325 341 | 
             
                  elsif data
         | 
| 326 342 | 
             
                    if data.respond_to?(:read)
         | 
| 327 343 | 
             
                      request.body_stream = data
         | 
| @@ -341,11 +357,15 @@ module OAuth | |
| 341 357 | 
             
                  request
         | 
| 342 358 | 
             
                end
         | 
| 343 359 |  | 
| 344 | 
            -
                # Unset cached http instance because it cannot be marshalled when
         | 
| 345 | 
            -
                # it has already been used and use_ssl is set to true
         | 
| 346 360 | 
             
                def marshal_dump(*args)
         | 
| 347 | 
            -
                   | 
| 348 | 
            -
             | 
| 361 | 
            +
                  {:key => @key,
         | 
| 362 | 
            +
                   :secret => @secret,
         | 
| 363 | 
            +
                   :options => @options}
         | 
| 364 | 
            +
                end
         | 
| 365 | 
            +
             | 
| 366 | 
            +
                def marshal_load(data)
         | 
| 367 | 
            +
                  initialize(data[:key], data[:secret], data[:options])
         | 
| 349 368 | 
             
                end
         | 
| 369 | 
            +
             | 
| 350 370 | 
             
              end
         | 
| 351 371 | 
             
            end
         |