gdata_plus 0.0.0
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.
- data/.document +5 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +35 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +51 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/examples/client_login_example.rb +15 -0
- data/examples/oauth_example.rb +37 -0
- data/gdata_plus.gemspec +93 -0
- data/lib/gdata_plus/authenticator/client_login.rb +60 -0
- data/lib/gdata_plus/authenticator/common.rb +9 -0
- data/lib/gdata_plus/authenticator/o_auth.rb +104 -0
- data/lib/gdata_plus/client.rb +48 -0
- data/lib/gdata_plus/exception.rb +15 -0
- data/lib/gdata_plus/util.rb +22 -0
- data/lib/gdata_plus.rb +11 -0
- data/test/authenticator/client_login_test.rb +8 -0
- data/test/authenticator/o_auth_test.rb +105 -0
- data/test/client_test.rb +66 -0
- data/test/exception_test.rb +15 -0
- data/test/helper.rb +19 -0
- metadata +213 -0
data/.document
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gem "activesupport"
|
4
|
+
gem "oauth"
|
5
|
+
gem "typhoeus"
|
6
|
+
|
7
|
+
# Add dependencies to develop your gem here.
|
8
|
+
# Include everything needed to run rake, tests, features, etc.
|
9
|
+
group :development do
|
10
|
+
gem "sinatra"
|
11
|
+
|
12
|
+
gem "shoulda", ">= 0"
|
13
|
+
gem "bundler", "~> 1.0.0"
|
14
|
+
gem "jeweler", "~> 1.5.1"
|
15
|
+
gem "mocha"
|
16
|
+
gem "rcov", ">= 0"
|
17
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activesupport (3.0.3)
|
5
|
+
git (1.2.5)
|
6
|
+
jeweler (1.5.1)
|
7
|
+
bundler (~> 1.0.0)
|
8
|
+
git (>= 1.2.5)
|
9
|
+
rake
|
10
|
+
mocha (0.9.10)
|
11
|
+
rake
|
12
|
+
oauth (0.4.4)
|
13
|
+
rack (1.2.1)
|
14
|
+
rake (0.8.7)
|
15
|
+
rcov (0.9.9)
|
16
|
+
shoulda (2.11.3)
|
17
|
+
sinatra (1.1.0)
|
18
|
+
rack (~> 1.1)
|
19
|
+
tilt (~> 1.1)
|
20
|
+
tilt (1.1)
|
21
|
+
typhoeus (0.2.0)
|
22
|
+
|
23
|
+
PLATFORMS
|
24
|
+
ruby
|
25
|
+
|
26
|
+
DEPENDENCIES
|
27
|
+
activesupport
|
28
|
+
bundler (~> 1.0.0)
|
29
|
+
jeweler (~> 1.5.1)
|
30
|
+
mocha
|
31
|
+
oauth
|
32
|
+
rcov
|
33
|
+
shoulda
|
34
|
+
sinatra
|
35
|
+
typhoeus
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Brian Alexander
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
= gdata_plus
|
2
|
+
|
3
|
+
{Source code}[https://github.com/balexand/gdata_plus] | {RDoc}[http://rubydoc.info/gems/gdata_plus/frames] | {Ruby Gem}[https://rubygems.org/gems/gdata_plus]
|
4
|
+
|
5
|
+
Simple, easy to use GData API that supports OAuth, Ruby 1.8/1.9 and uses Typhoeus as an HTTP client.
|
6
|
+
|
7
|
+
== Installation
|
8
|
+
|
9
|
+
gem install gdata_plus
|
10
|
+
|
11
|
+
== Authentication
|
12
|
+
|
13
|
+
=== OAuth
|
14
|
+
|
15
|
+
TODO
|
16
|
+
|
17
|
+
==== Using an existing access token
|
18
|
+
|
19
|
+
TODO
|
20
|
+
|
21
|
+
=== ClientLogin
|
22
|
+
|
23
|
+
TODO
|
24
|
+
|
25
|
+
=== Serializing authenticators
|
26
|
+
|
27
|
+
TODO
|
28
|
+
|
29
|
+
== Making requests
|
30
|
+
|
31
|
+
TODO
|
32
|
+
|
33
|
+
== Error handling
|
34
|
+
|
35
|
+
TODO
|
36
|
+
|
37
|
+
== Ruby support
|
38
|
+
|
39
|
+
This project is tested against Ruby 1.8.7 and Ruby 1.9.2. There is an {issue}[https://github.com/balexand/gdata_plus/issues/1] with international characters and OAuth that affects Ruby 1.8.7.
|
40
|
+
|
41
|
+
== Contributions
|
42
|
+
|
43
|
+
This project is actively maintained. Please submit an issue if you find any bugs or want to request a new feature. Contributions are welcome. Please run the tests with Ruby 1.9.2 and 1.8.7 before submitting a pull request:
|
44
|
+
|
45
|
+
rake test
|
46
|
+
|
47
|
+
== Copyright
|
48
|
+
|
49
|
+
Copyright (c) 2010 Brian Alexander. See LICENSE.txt for
|
50
|
+
further details.
|
51
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'rake'
|
11
|
+
|
12
|
+
require 'jeweler'
|
13
|
+
Jeweler::Tasks.new do |gem|
|
14
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
+
gem.name = "gdata_plus"
|
16
|
+
gem.homepage = "http://github.com/balexand/gdata_plus"
|
17
|
+
gem.license = "MIT"
|
18
|
+
gem.summary = %Q{Simple, easy to use GData API that supports OAuth, Ruby 1.8/1.9 and uses Typhoeus as an HTTP client}
|
19
|
+
gem.description = %Q{Simple, easy to use GData API that supports OAuth, Ruby 1.8/1.9 and uses Typhoeus as an HTTP client}
|
20
|
+
gem.email = "balexand@gmail.com"
|
21
|
+
gem.authors = ["Brian Alexander"]
|
22
|
+
|
23
|
+
gem.files.exclude "examples"
|
24
|
+
end
|
25
|
+
Jeweler::RubygemsDotOrgTasks.new
|
26
|
+
|
27
|
+
require 'rake/testtask'
|
28
|
+
Rake::TestTask.new(:test) do |test|
|
29
|
+
test.libs << 'lib' << 'test'
|
30
|
+
test.pattern = 'test/**/*_test.rb'
|
31
|
+
test.verbose = true
|
32
|
+
end
|
33
|
+
|
34
|
+
require 'rcov/rcovtask'
|
35
|
+
Rcov::RcovTask.new do |test|
|
36
|
+
test.libs << 'test'
|
37
|
+
test.pattern = 'test/**/*_test.rb'
|
38
|
+
test.verbose = true
|
39
|
+
end
|
40
|
+
|
41
|
+
task :default => :test
|
42
|
+
|
43
|
+
require 'rake/rdoctask'
|
44
|
+
Rake::RDocTask.new do |rdoc|
|
45
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
46
|
+
|
47
|
+
rdoc.rdoc_dir = 'rdoc'
|
48
|
+
rdoc.title = "gdata_plus #{version}"
|
49
|
+
rdoc.rdoc_files.include('README*')
|
50
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
51
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'gdata_plus'
|
3
|
+
require 'highline/import' # gem install highline
|
4
|
+
require 'typhoeus'
|
5
|
+
|
6
|
+
# prompt for email/password
|
7
|
+
email = ask("Enter your email: ")
|
8
|
+
password = ask("Enter your password: ") { |q| q.echo = "x" }
|
9
|
+
|
10
|
+
# authenticate using email/password
|
11
|
+
authenticator = GDataPlus::Authenticator::ClientLogin.new(:service => "lh2", :source => "balexand-gdata_plus-1")
|
12
|
+
authenticator.authenticate(email, password)
|
13
|
+
|
14
|
+
response = authenticator.client.get("https://picasaweb.google.com/data/feed/api/user/default")
|
15
|
+
puts response.inspect
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# you don't need the following line if you've installed the gem
|
2
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
3
|
+
|
4
|
+
require 'gdata_plus'
|
5
|
+
require 'sinatra'
|
6
|
+
require 'typhoeus'
|
7
|
+
|
8
|
+
# NOTE: put your consumer key and secret here or set environment vars
|
9
|
+
CONSUMER_KEY = ENV["GDATA_CONSUMER_KEY"]
|
10
|
+
CONSUMER_SECRET = ENV["GDATA_CONSUMER_SECRET"]
|
11
|
+
|
12
|
+
set :sessions, true # enable Sinatra sessions
|
13
|
+
|
14
|
+
get "/" do
|
15
|
+
oauth_callback = "#{request.scheme}://#{request.host}:#{request.port}/callback"
|
16
|
+
|
17
|
+
authenticator = GDataPlus::Authenticator::OAuth.new(:consumer_key => CONSUMER_KEY, :consumer_secret => CONSUMER_SECRET)
|
18
|
+
request_token = authenticator.fetch_request_token(:scope => "https://picasaweb.google.com/data/", :oauth_callback => oauth_callback)
|
19
|
+
|
20
|
+
# store authenticator in the session since we'll need it when exchanging request token for an access token
|
21
|
+
session[:gdata_authenticator] = authenticator
|
22
|
+
|
23
|
+
redirect request_token.authorize_url
|
24
|
+
end
|
25
|
+
|
26
|
+
get "/callback" do
|
27
|
+
authenticator = session[:gdata_authenticator]
|
28
|
+
authenticator.fetch_access_token(params[:oauth_verifier])
|
29
|
+
redirect "/picasa_album_list"
|
30
|
+
end
|
31
|
+
|
32
|
+
get "/picasa_album_list" do
|
33
|
+
authenticator = session[:gdata_authenticator]
|
34
|
+
response = authenticator.client.get("https://picasaweb.google.com/data/feed/api/user/default")
|
35
|
+
|
36
|
+
response.inspect
|
37
|
+
end
|
data/gdata_plus.gemspec
ADDED
@@ -0,0 +1,93 @@
|
|
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{gdata_plus}
|
8
|
+
s.version = "0.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Brian Alexander"]
|
12
|
+
s.date = %q{2010-12-31}
|
13
|
+
s.description = %q{Simple, easy to use GData API that supports OAuth, Ruby 1.8/1.9 and uses Typhoeus as an HTTP client}
|
14
|
+
s.email = %q{balexand@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
"Gemfile",
|
22
|
+
"Gemfile.lock",
|
23
|
+
"LICENSE.txt",
|
24
|
+
"README.rdoc",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"gdata_plus.gemspec",
|
28
|
+
"lib/gdata_plus.rb",
|
29
|
+
"lib/gdata_plus/authenticator/client_login.rb",
|
30
|
+
"lib/gdata_plus/authenticator/common.rb",
|
31
|
+
"lib/gdata_plus/authenticator/o_auth.rb",
|
32
|
+
"lib/gdata_plus/client.rb",
|
33
|
+
"lib/gdata_plus/exception.rb",
|
34
|
+
"lib/gdata_plus/util.rb",
|
35
|
+
"test/authenticator/client_login_test.rb",
|
36
|
+
"test/authenticator/o_auth_test.rb",
|
37
|
+
"test/client_test.rb",
|
38
|
+
"test/exception_test.rb",
|
39
|
+
"test/helper.rb"
|
40
|
+
]
|
41
|
+
s.homepage = %q{http://github.com/balexand/gdata_plus}
|
42
|
+
s.licenses = ["MIT"]
|
43
|
+
s.require_paths = ["lib"]
|
44
|
+
s.rubygems_version = %q{1.3.7}
|
45
|
+
s.summary = %q{Simple, easy to use GData API that supports OAuth, Ruby 1.8/1.9 and uses Typhoeus as an HTTP client}
|
46
|
+
s.test_files = [
|
47
|
+
"examples/client_login_example.rb",
|
48
|
+
"examples/oauth_example.rb",
|
49
|
+
"test/authenticator/client_login_test.rb",
|
50
|
+
"test/authenticator/o_auth_test.rb",
|
51
|
+
"test/client_test.rb",
|
52
|
+
"test/exception_test.rb",
|
53
|
+
"test/helper.rb"
|
54
|
+
]
|
55
|
+
|
56
|
+
if s.respond_to? :specification_version then
|
57
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
58
|
+
s.specification_version = 3
|
59
|
+
|
60
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
61
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 0"])
|
62
|
+
s.add_runtime_dependency(%q<oauth>, [">= 0"])
|
63
|
+
s.add_runtime_dependency(%q<typhoeus>, [">= 0"])
|
64
|
+
s.add_development_dependency(%q<sinatra>, [">= 0"])
|
65
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
66
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
67
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
|
68
|
+
s.add_development_dependency(%q<mocha>, [">= 0"])
|
69
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
70
|
+
else
|
71
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
72
|
+
s.add_dependency(%q<oauth>, [">= 0"])
|
73
|
+
s.add_dependency(%q<typhoeus>, [">= 0"])
|
74
|
+
s.add_dependency(%q<sinatra>, [">= 0"])
|
75
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
76
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
77
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
|
78
|
+
s.add_dependency(%q<mocha>, [">= 0"])
|
79
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
80
|
+
end
|
81
|
+
else
|
82
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
83
|
+
s.add_dependency(%q<oauth>, [">= 0"])
|
84
|
+
s.add_dependency(%q<typhoeus>, [">= 0"])
|
85
|
+
s.add_dependency(%q<sinatra>, [">= 0"])
|
86
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
87
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
88
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
|
89
|
+
s.add_dependency(%q<mocha>, [">= 0"])
|
90
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'typhoeus'
|
2
|
+
|
3
|
+
module GDataPlus
|
4
|
+
module Authenticator
|
5
|
+
class ClientLogin
|
6
|
+
include Common
|
7
|
+
|
8
|
+
# {Account type GOOGLE}[http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html#Request]
|
9
|
+
TYPE_GOOGLE = "GOOGLE"
|
10
|
+
# {Account type HOSTED}[http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html#Request]
|
11
|
+
TYPE_HOSTED = "HOSTED"
|
12
|
+
# {Account type HOSTED_OR_GOOGLE}[http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html#Request]
|
13
|
+
TYPE_HOSTED_OR_GOOGLE = "HOSTED_OR_GOOGLE"
|
14
|
+
|
15
|
+
attr_accessor :auth_token
|
16
|
+
|
17
|
+
# === Options
|
18
|
+
# [:service]
|
19
|
+
# (required) Name of service to which you are authenticating.
|
20
|
+
# {Click here for a list of possible values}[http://code.google.com/apis/gdata/faq.html#clientlogin].
|
21
|
+
# [:source]
|
22
|
+
# (required) Short string identifying your application, for logging purposes. This string should take
|
23
|
+
# the form: "companyName-applicationName-versionID".
|
24
|
+
# [:account_type]
|
25
|
+
# Account type to login. Defaults to TYPE_HOSTED_OR_GOOGLE.
|
26
|
+
# {Click here for details}[http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html#Request].
|
27
|
+
def initialize(options = {})
|
28
|
+
options = Util.prepare_options(options, [:service, :source], [:account_type])
|
29
|
+
options[:account_type] ||= TYPE_HOSTED_OR_GOOGLE
|
30
|
+
|
31
|
+
@service = options[:service]
|
32
|
+
@source = options[:source]
|
33
|
+
@account_type = options[:account_type]
|
34
|
+
end
|
35
|
+
|
36
|
+
def authenticate(email, password, hydra = Typhoeus::Hydra.new)
|
37
|
+
request = Typhoeus::Request.new("https://www.google.com/accounts/ClientLogin", :method => :post, :params => {
|
38
|
+
:accountType => @accountType,
|
39
|
+
:Email => email,
|
40
|
+
:Passwd => password,
|
41
|
+
:service => @service,
|
42
|
+
:source => @source
|
43
|
+
})
|
44
|
+
|
45
|
+
hydra.queue request
|
46
|
+
hydra.run
|
47
|
+
response = request.response
|
48
|
+
|
49
|
+
Util.raise_if_error(response)
|
50
|
+
@auth_token = /Auth=(.+)$/.match(response.body)[1]
|
51
|
+
end
|
52
|
+
|
53
|
+
def sign_request(request)
|
54
|
+
raise ArgumentError, "request must be a Typeoeus::Request" unless request.is_a? ::Typhoeus::Request
|
55
|
+
request.headers["Authorization"] = "GoogleLogin auth=#{@auth_token}"
|
56
|
+
request
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'oauth'
|
2
|
+
require 'oauth/request_proxy/typhoeus_request'
|
3
|
+
require 'typhoeus'
|
4
|
+
|
5
|
+
# Methods prefixed with "fetch" indicate that a request is being made to Google.
|
6
|
+
module GDataPlus
|
7
|
+
module Authenticator
|
8
|
+
class OAuth
|
9
|
+
include Common
|
10
|
+
|
11
|
+
# Create a new instance.
|
12
|
+
#
|
13
|
+
# === Options
|
14
|
+
# [:consumer_key] (required)
|
15
|
+
# [:consumer_secret] (required)
|
16
|
+
# TODO document optional options
|
17
|
+
def initialize(options = {})
|
18
|
+
required_options = [:consumer_key, :consumer_secret]
|
19
|
+
optional_options = [:request_token, :request_secret, :access_token, :access_secret]
|
20
|
+
options = Util.prepare_options(options, required_options, optional_options)
|
21
|
+
|
22
|
+
(required_options + optional_options).each do |option_name|
|
23
|
+
instance_variable_set :"@#{option_name}", options[option_name]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def consumer
|
28
|
+
::OAuth::Consumer.new(@consumer_key, @consumer_secret,
|
29
|
+
:request_token_url => "https://www.google.com/accounts/OAuthGetRequestToken",
|
30
|
+
:authorize_url => "https://www.google.com/accounts/OAuthAuthorizeToken",
|
31
|
+
:access_token_url => "https://www.google.com/accounts/OAuthGetAccessToken"
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
# === Arguments
|
36
|
+
# [options] (required) see options documentation below
|
37
|
+
# [additional_oauth_options]
|
38
|
+
# additional oauth params to pass to
|
39
|
+
# {get_request_token}[http://rdoc.info/github/oauth/oauth-ruby/master/OAuth/Consumer#get_request_token-instance_method];
|
40
|
+
# you will normally leave this blank
|
41
|
+
# [additional_request_params]
|
42
|
+
# additional params to pass with request; you will normally leave this blank
|
43
|
+
#
|
44
|
+
# === Options
|
45
|
+
# [:scope]
|
46
|
+
# (required) gdata {scope}[http://code.google.com/apis/gdata/faq.html#AuthScopes]; can be an Array or a String
|
47
|
+
# [:oauth_callback]
|
48
|
+
# (required) Google will redirect the user back to this URL after authentication
|
49
|
+
def fetch_request_token(options = {}, additional_oauth_options = {}, additional_request_params = {})
|
50
|
+
options = ::GDataPlus::Util.prepare_options(options, [:scope, :oauth_callback])
|
51
|
+
|
52
|
+
additional_oauth_options.merge!(:oauth_callback => options[:oauth_callback])
|
53
|
+
|
54
|
+
scope = options[:scope]
|
55
|
+
scope = scope.join(" ") if scope.is_a? Array
|
56
|
+
additional_request_params.merge!(:scope => scope)
|
57
|
+
|
58
|
+
request_token = consumer.get_request_token(additional_oauth_options, additional_request_params)
|
59
|
+
@request_token = request_token.token
|
60
|
+
@request_secret = request_token.secret
|
61
|
+
request_token
|
62
|
+
# TODO deal with error response
|
63
|
+
end
|
64
|
+
|
65
|
+
def request_token
|
66
|
+
if @request_token && @request_secret
|
67
|
+
::OAuth::RequestToken.new(consumer, @request_token, @request_secret)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Exchanges the request token for the access token. The "oauth_verifier" is passed as a
|
72
|
+
# URL parameter when Google redirects the client back to your oauth_callback URL.
|
73
|
+
def fetch_access_token(oauth_verifier)
|
74
|
+
access_token = request_token.get_access_token(:oauth_verifier => oauth_verifier)
|
75
|
+
@access_token = access_token.token
|
76
|
+
@access_secret = access_token.secret
|
77
|
+
@request_token = nil
|
78
|
+
@request_secret = nil
|
79
|
+
access_token
|
80
|
+
|
81
|
+
# TODO deal with error response
|
82
|
+
end
|
83
|
+
|
84
|
+
def access_token
|
85
|
+
if @access_token && @access_secret
|
86
|
+
::OAuth::AccessToken.new(consumer, @access_token, @access_secret)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Adds authorization header to the specified Typeoeus::Request. The same request is also returned.
|
91
|
+
def sign_request(request)
|
92
|
+
raise ArgumentError, "request must be a Typeoeus::Request" unless request.is_a? ::Typhoeus::Request
|
93
|
+
|
94
|
+
helper = ::OAuth::Client::Helper.new(request, {
|
95
|
+
:consumer => consumer,
|
96
|
+
:request_uri => request.url,
|
97
|
+
:token => access_token
|
98
|
+
})
|
99
|
+
request.headers.merge!({"Authorization" => helper.header})
|
100
|
+
request
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'typhoeus'
|
2
|
+
|
3
|
+
module GDataPlus
|
4
|
+
class Client
|
5
|
+
attr_reader :authenticator, :default_gdata_version
|
6
|
+
|
7
|
+
def initialize(authenticator, default_gdata_version = "2.0")
|
8
|
+
@authenticator = authenticator
|
9
|
+
@default_gdata_version = default_gdata_version
|
10
|
+
end
|
11
|
+
|
12
|
+
# FIXME detect infinite redirect
|
13
|
+
def submit(request, options = {})
|
14
|
+
options = ::GDataPlus::Util.prepare_options(options, [], [:gdata_version, :hydra, :no_redirect])
|
15
|
+
hydra = options[:hydra] || Typhoeus::Hydra.hydra
|
16
|
+
|
17
|
+
request.headers.merge!("GData-Version" => options[:gdata_version] || default_gdata_version)
|
18
|
+
@authenticator.sign_request(request)
|
19
|
+
|
20
|
+
# add "If-Match: *" header if there is not already a conditional header
|
21
|
+
unless request.headers.keys.any? { |key| key =~ /^If-/ }
|
22
|
+
request.headers.merge!("If-Match" => "*")
|
23
|
+
end
|
24
|
+
|
25
|
+
hydra.queue(request)
|
26
|
+
hydra.run
|
27
|
+
response = request.response
|
28
|
+
|
29
|
+
# automatically follow redirects since some GData APIs (like Calendar) redirect GET requests
|
30
|
+
if request.method.to_sym == :get && !options[:no_redirect] && (300..399).include?(response.code)
|
31
|
+
response = submit ::Typhoeus::Request.new(response.headers_hash["Location"], :method => :get), options.merge(:no_redirect => true)
|
32
|
+
end
|
33
|
+
|
34
|
+
Util.raise_if_error(response)
|
35
|
+
|
36
|
+
response
|
37
|
+
end
|
38
|
+
|
39
|
+
[:delete, :get, :post, :put].each do |method|
|
40
|
+
define_method(method) do |*args|
|
41
|
+
args[1] ||= {}
|
42
|
+
args[1] = args[1].merge(:method => method)
|
43
|
+
request = ::Typhoeus::Request.new(*args)
|
44
|
+
submit request
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module GDataPlus
|
2
|
+
class Exception < StandardError
|
3
|
+
attr_reader :response
|
4
|
+
|
5
|
+
def initialize(response)
|
6
|
+
@response = response
|
7
|
+
|
8
|
+
if @response.respond_to? :body
|
9
|
+
super(@response.body)
|
10
|
+
else
|
11
|
+
super("no response provided")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'active_support/core_ext/hash/keys'
|
2
|
+
|
3
|
+
module GDataPlus
|
4
|
+
module Util
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def prepare_options(options, required_keys, optional_keys = [])
|
8
|
+
options = options.symbolize_keys
|
9
|
+
options.assert_valid_keys(required_keys + optional_keys)
|
10
|
+
required_keys.each do |key|
|
11
|
+
raise ArgumentError, "#{key.inspect} option required" if options[key].nil?
|
12
|
+
end
|
13
|
+
options
|
14
|
+
end
|
15
|
+
|
16
|
+
def raise_if_error(response)
|
17
|
+
unless (200..299).include? response.code
|
18
|
+
raise Exception.new(response)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/gdata_plus.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
module GDataPlus
|
2
|
+
autoload "Client", "gdata_plus/client"
|
3
|
+
autoload "Exception", "gdata_plus/exception"
|
4
|
+
autoload "Util", "gdata_plus/util"
|
5
|
+
|
6
|
+
module Authenticator
|
7
|
+
autoload "ClientLogin", "gdata_plus/authenticator/client_login"
|
8
|
+
autoload "Common", "gdata_plus/authenticator/common"
|
9
|
+
autoload "OAuth", "gdata_plus/authenticator/o_auth"
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'typhoeus'
|
3
|
+
|
4
|
+
class OAuthTest < Test::Unit::TestCase
|
5
|
+
def valid_constructor_options
|
6
|
+
{
|
7
|
+
:consumer_key => "1234",
|
8
|
+
"consumer_secret" => "5678"
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
def valid_request_token_options
|
13
|
+
{
|
14
|
+
:oauth_callback => "http://example.com/callback",
|
15
|
+
:scope => "https://docs.google.com/feeds/"
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
should "initialize" do
|
20
|
+
authenticator = GDataPlus::Authenticator::OAuth.new(valid_constructor_options)
|
21
|
+
assert authenticator.consumer.is_a? OAuth::Consumer
|
22
|
+
end
|
23
|
+
|
24
|
+
should "initialize raise if invalid options passed" do
|
25
|
+
assert_raises(ArgumentError) do
|
26
|
+
GDataPlus::Authenticator::OAuth.new(valid_constructor_options.merge(:consumer_key => nil))
|
27
|
+
end
|
28
|
+
|
29
|
+
assert_raises(ArgumentError) do
|
30
|
+
GDataPlus::Authenticator::OAuth.new(valid_constructor_options.merge(:foo => 'bar'))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
should "fetch_request_token raise if invalid options passed" do
|
35
|
+
authenticator = GDataPlus::Authenticator::OAuth.new(valid_constructor_options)
|
36
|
+
assert_raises(ArgumentError) do
|
37
|
+
authenticator.fetch_request_token(valid_request_token_options.merge(:scope => nil))
|
38
|
+
end
|
39
|
+
|
40
|
+
assert_raises(ArgumentError) do
|
41
|
+
authenticator.fetch_request_token(valid_request_token_options.merge(:foo => "bar"))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
should "sign_request raise if invalid request passed" do
|
46
|
+
authenticator = GDataPlus::Authenticator::OAuth.new(valid_constructor_options)
|
47
|
+
exception = assert_raises(ArgumentError) do
|
48
|
+
authenticator.sign_request("I'm not a request object")
|
49
|
+
end
|
50
|
+
assert_equal "request must be a Typeoeus::Request", exception.message
|
51
|
+
end
|
52
|
+
|
53
|
+
# uses "Example used in the OAuth Specification" from http://hueniverse.com/2008/10/beginners-guide-to-oauth-part-iv-signing-requests/
|
54
|
+
should "complete oauth workflow" do
|
55
|
+
authenticator = GDataPlus::Authenticator::OAuth.new(:consumer_key => "dpf43f3p2l4k3l03", :consumer_secret => "kd94hf93k423kf44")
|
56
|
+
|
57
|
+
request_token_stub = stub(:token => "foo_request_token", :secret => "bar_request_token_secret")
|
58
|
+
OAuth::Consumer.any_instance.expects(:get_request_token).once.returns(request_token_stub)
|
59
|
+
|
60
|
+
request_token = authenticator.fetch_request_token(:scope => "https://picasaweb.google.com/data/", :oauth_callback => "http://mysite.com/callback")
|
61
|
+
assert_equal request_token_stub, request_token
|
62
|
+
|
63
|
+
access_token_stub = stub(:token => "nnch734d00sl2jdk", :secret => "pfkkdhi9sl3r4s00")
|
64
|
+
OAuth::RequestToken.any_instance.expects(:get_access_token).once.returns(access_token_stub)
|
65
|
+
|
66
|
+
access_token = authenticator.fetch_access_token("foo_oauth_verifier")
|
67
|
+
assert_equal access_token_stub, access_token
|
68
|
+
|
69
|
+
OAuth::Client::Helper.any_instance.expects(:nonce).once.returns("kllo9940pd9333jh")
|
70
|
+
OAuth::Client::Helper.any_instance.expects(:timestamp).once.returns("1191242096")
|
71
|
+
|
72
|
+
request = Typhoeus::Request.new("http://photos.example.net/photos?size=original&file=vacation.jpg")
|
73
|
+
authenticator.sign_request(request)
|
74
|
+
|
75
|
+
assert request.headers["Authorization"] =~ /oauth_signature="tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D"/,
|
76
|
+
"wrong oauth_signature in Authorization header"
|
77
|
+
end
|
78
|
+
|
79
|
+
# uses "Non-English Parameter" with some custom unicode params from
|
80
|
+
# http://hueniverse.com/2008/10/beginners-guide-to-oauth-part-iv-signing-requests/
|
81
|
+
should "sign_request with international characters" do
|
82
|
+
authenticator = GDataPlus::Authenticator::OAuth.new(
|
83
|
+
:consumer_key => "dpf43f3++p+#2l4k3l03",
|
84
|
+
:consumer_secret => "kd9@4h%%4f93k423kf44",
|
85
|
+
:access_token => "nnch734d(0)0sl2jdk",
|
86
|
+
:access_secret => "pfkkd#hi9_sl-3r=4s00"
|
87
|
+
)
|
88
|
+
|
89
|
+
params = {
|
90
|
+
:latin => "123abc\u00E7",
|
91
|
+
:hebrew => "\u05DC\u05E9",
|
92
|
+
:arabic => "\u0642\u0644"
|
93
|
+
}
|
94
|
+
param_string = params.collect {|k,v| "#{k}=#{CGI.escape(v)}"}.join("&")
|
95
|
+
request = Typhoeus::Request.new("https://bar.example.net/foo?#{param_string}")
|
96
|
+
|
97
|
+
# stub out nonce and timestamp methods
|
98
|
+
OAuth::Client::Helper.any_instance.expects(:nonce).once.returns("kllo~9940~pd9333jh")
|
99
|
+
OAuth::Client::Helper.any_instance.expects(:timestamp).once.returns("1191242096")
|
100
|
+
|
101
|
+
authenticator.sign_request(request)
|
102
|
+
assert request.headers["Authorization"] =~ /oauth_signature="dNDB%2Fb%2BPVt1mnLW0bJAhWo4Jkww%3D"/,
|
103
|
+
"wrong oauth_signature in Authorization header; this is know to fail in Ruby 1.8 but works in 1.9; anyone want to contribute a patch?"
|
104
|
+
end
|
105
|
+
end
|
data/test/client_test.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'typhoeus'
|
3
|
+
|
4
|
+
class ClientTest < Test::Unit::TestCase
|
5
|
+
# TODO add a test that ensures the If-Match: * is not added if there is already a conditional header
|
6
|
+
should "automatically add If-Match header if an If-* header not already present" do
|
7
|
+
url = "http://foo.com/bar"
|
8
|
+
|
9
|
+
hydra = Typhoeus::Hydra.new
|
10
|
+
hydra.stub(:get, url).and_return(
|
11
|
+
Typhoeus::Response.new(:code => 200, :body => "the body", :time => 0.1)
|
12
|
+
)
|
13
|
+
|
14
|
+
# stub authenticator to do nothing
|
15
|
+
authenticator = Object.new
|
16
|
+
authenticator.expects(:sign_request).once
|
17
|
+
|
18
|
+
client = ::GDataPlus::Client.new(authenticator)
|
19
|
+
request = Typhoeus::Request.new(url, :method => :get)
|
20
|
+
response = client.submit(request, :hydra => hydra)
|
21
|
+
assert_equal 200, response.code
|
22
|
+
|
23
|
+
assert_equal "*", request.headers["If-Match"]
|
24
|
+
end
|
25
|
+
|
26
|
+
should "automatically follow redirects" do
|
27
|
+
# stub Tyhoeus hydra to return dummy responses
|
28
|
+
hydra = Typhoeus::Hydra.new
|
29
|
+
urls = ["http://example.com/foo", "http://example.com/bar"]
|
30
|
+
hydra.stub(:get, urls[0]).and_return(
|
31
|
+
Typhoeus::Response.new(:code => 301, :headers => "Location: #{urls[1]}", :body => "", :time => 0.1)
|
32
|
+
)
|
33
|
+
hydra.stub(:get, urls[1]).and_return(
|
34
|
+
Typhoeus::Response.new(:code => 200, :body => "the body", :time => 0.1)
|
35
|
+
)
|
36
|
+
|
37
|
+
# stub authenticator to do nothing
|
38
|
+
authenticator = Object.new
|
39
|
+
authenticator.expects(:sign_request).twice
|
40
|
+
|
41
|
+
client = ::GDataPlus::Client.new(authenticator)
|
42
|
+
response = client.submit(Typhoeus::Request.new(urls[0], :method => :get), :hydra => hydra)
|
43
|
+
assert_equal 200, response.code
|
44
|
+
assert_equal "the body", response.body
|
45
|
+
end
|
46
|
+
|
47
|
+
should "prevent redirect loop by only automatically redirecting once" do
|
48
|
+
# stub Tyhoeus hydra to return dummy responses
|
49
|
+
hydra = Typhoeus::Hydra.new
|
50
|
+
urls = ["http://example.com/foo", "http://example.com/bar"]
|
51
|
+
urls.size.times do |index|
|
52
|
+
response = Typhoeus::Response.new(:code => 302, :headers => "Location: #{urls[(index+1)%2]}", :body => "", :time => 0.1)
|
53
|
+
hydra.stub(:get, urls[index]).and_return(response)
|
54
|
+
end
|
55
|
+
|
56
|
+
# stub authenticator to do nothing; if it's called more than two times then we're in a redirect loop
|
57
|
+
authenticator = Object.new
|
58
|
+
authenticator.expects(:sign_request).twice
|
59
|
+
|
60
|
+
client = ::GDataPlus::Client.new(authenticator)
|
61
|
+
exception = assert_raises(::GDataPlus::Exception) do
|
62
|
+
client.submit(Typhoeus::Request.new(urls[0], :method => :get), :hydra => hydra)
|
63
|
+
end
|
64
|
+
assert_equal 302, exception.response.code
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class ExceptionTest < Test::Unit::TestCase
|
4
|
+
should "initialize with unknown response" do
|
5
|
+
e = ::GDataPlus::Exception.new(nil)
|
6
|
+
assert_equal "no response provided", e.message
|
7
|
+
end
|
8
|
+
|
9
|
+
should "initialize with response" do
|
10
|
+
response_stub = stub(:body => "foo bar message")
|
11
|
+
e = ::GDataPlus::Exception.new(response_stub)
|
12
|
+
assert_equal "foo bar message", e.message
|
13
|
+
assert_equal response_stub, e.response
|
14
|
+
end
|
15
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
require 'shoulda'
|
12
|
+
require 'mocha'
|
13
|
+
|
14
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
15
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
16
|
+
require 'gdata_plus'
|
17
|
+
|
18
|
+
class Test::Unit::TestCase
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gdata_plus
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 0.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Brian Alexander
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-12-31 00:00:00 -08:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: activesupport
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
prerelease: false
|
32
|
+
version_requirements: *id001
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: oauth
|
35
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
segments:
|
41
|
+
- 0
|
42
|
+
version: "0"
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: *id002
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: typhoeus
|
48
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
segments:
|
54
|
+
- 0
|
55
|
+
version: "0"
|
56
|
+
type: :runtime
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *id003
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: sinatra
|
61
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
segments:
|
67
|
+
- 0
|
68
|
+
version: "0"
|
69
|
+
type: :development
|
70
|
+
prerelease: false
|
71
|
+
version_requirements: *id004
|
72
|
+
- !ruby/object:Gem::Dependency
|
73
|
+
name: shoulda
|
74
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
segments:
|
80
|
+
- 0
|
81
|
+
version: "0"
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: *id005
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: bundler
|
87
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ~>
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
segments:
|
93
|
+
- 1
|
94
|
+
- 0
|
95
|
+
- 0
|
96
|
+
version: 1.0.0
|
97
|
+
type: :development
|
98
|
+
prerelease: false
|
99
|
+
version_requirements: *id006
|
100
|
+
- !ruby/object:Gem::Dependency
|
101
|
+
name: jeweler
|
102
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
103
|
+
none: false
|
104
|
+
requirements:
|
105
|
+
- - ~>
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
segments:
|
108
|
+
- 1
|
109
|
+
- 5
|
110
|
+
- 1
|
111
|
+
version: 1.5.1
|
112
|
+
type: :development
|
113
|
+
prerelease: false
|
114
|
+
version_requirements: *id007
|
115
|
+
- !ruby/object:Gem::Dependency
|
116
|
+
name: mocha
|
117
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
118
|
+
none: false
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
segments:
|
123
|
+
- 0
|
124
|
+
version: "0"
|
125
|
+
type: :development
|
126
|
+
prerelease: false
|
127
|
+
version_requirements: *id008
|
128
|
+
- !ruby/object:Gem::Dependency
|
129
|
+
name: rcov
|
130
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
131
|
+
none: false
|
132
|
+
requirements:
|
133
|
+
- - ">="
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
segments:
|
136
|
+
- 0
|
137
|
+
version: "0"
|
138
|
+
type: :development
|
139
|
+
prerelease: false
|
140
|
+
version_requirements: *id009
|
141
|
+
description: Simple, easy to use GData API that supports OAuth, Ruby 1.8/1.9 and uses Typhoeus as an HTTP client
|
142
|
+
email: balexand@gmail.com
|
143
|
+
executables: []
|
144
|
+
|
145
|
+
extensions: []
|
146
|
+
|
147
|
+
extra_rdoc_files:
|
148
|
+
- LICENSE.txt
|
149
|
+
- README.rdoc
|
150
|
+
files:
|
151
|
+
- .document
|
152
|
+
- Gemfile
|
153
|
+
- Gemfile.lock
|
154
|
+
- LICENSE.txt
|
155
|
+
- README.rdoc
|
156
|
+
- Rakefile
|
157
|
+
- VERSION
|
158
|
+
- gdata_plus.gemspec
|
159
|
+
- lib/gdata_plus.rb
|
160
|
+
- lib/gdata_plus/authenticator/client_login.rb
|
161
|
+
- lib/gdata_plus/authenticator/common.rb
|
162
|
+
- lib/gdata_plus/authenticator/o_auth.rb
|
163
|
+
- lib/gdata_plus/client.rb
|
164
|
+
- lib/gdata_plus/exception.rb
|
165
|
+
- lib/gdata_plus/util.rb
|
166
|
+
- test/authenticator/client_login_test.rb
|
167
|
+
- test/authenticator/o_auth_test.rb
|
168
|
+
- test/client_test.rb
|
169
|
+
- test/exception_test.rb
|
170
|
+
- test/helper.rb
|
171
|
+
- examples/client_login_example.rb
|
172
|
+
- examples/oauth_example.rb
|
173
|
+
has_rdoc: true
|
174
|
+
homepage: http://github.com/balexand/gdata_plus
|
175
|
+
licenses:
|
176
|
+
- MIT
|
177
|
+
post_install_message:
|
178
|
+
rdoc_options: []
|
179
|
+
|
180
|
+
require_paths:
|
181
|
+
- lib
|
182
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
183
|
+
none: false
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
hash: -4078657378247043019
|
188
|
+
segments:
|
189
|
+
- 0
|
190
|
+
version: "0"
|
191
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
192
|
+
none: false
|
193
|
+
requirements:
|
194
|
+
- - ">="
|
195
|
+
- !ruby/object:Gem::Version
|
196
|
+
segments:
|
197
|
+
- 0
|
198
|
+
version: "0"
|
199
|
+
requirements: []
|
200
|
+
|
201
|
+
rubyforge_project:
|
202
|
+
rubygems_version: 1.3.7
|
203
|
+
signing_key:
|
204
|
+
specification_version: 3
|
205
|
+
summary: Simple, easy to use GData API that supports OAuth, Ruby 1.8/1.9 and uses Typhoeus as an HTTP client
|
206
|
+
test_files:
|
207
|
+
- examples/client_login_example.rb
|
208
|
+
- examples/oauth_example.rb
|
209
|
+
- test/authenticator/client_login_test.rb
|
210
|
+
- test/authenticator/o_auth_test.rb
|
211
|
+
- test/client_test.rb
|
212
|
+
- test/exception_test.rb
|
213
|
+
- test/helper.rb
|