gdata-19 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/.gitignore +8 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +202 -0
  4. data/README +97 -0
  5. data/Rakefile +2 -0
  6. data/gdata.gemspec +44 -0
  7. data/lib/gdata.rb +24 -0
  8. data/lib/gdata/auth.rb +22 -0
  9. data/lib/gdata/auth/authsub.rb +161 -0
  10. data/lib/gdata/auth/clientlogin.rb +102 -0
  11. data/lib/gdata/client.rb +84 -0
  12. data/lib/gdata/client/apps.rb +27 -0
  13. data/lib/gdata/client/base.rb +182 -0
  14. data/lib/gdata/client/blogger.rb +28 -0
  15. data/lib/gdata/client/booksearch.rb +28 -0
  16. data/lib/gdata/client/calendar.rb +58 -0
  17. data/lib/gdata/client/contacts.rb +28 -0
  18. data/lib/gdata/client/doclist.rb +28 -0
  19. data/lib/gdata/client/finance.rb +28 -0
  20. data/lib/gdata/client/gbase.rb +28 -0
  21. data/lib/gdata/client/gmail.rb +28 -0
  22. data/lib/gdata/client/health.rb +28 -0
  23. data/lib/gdata/client/notebook.rb +28 -0
  24. data/lib/gdata/client/photos.rb +29 -0
  25. data/lib/gdata/client/spreadsheets.rb +28 -0
  26. data/lib/gdata/client/webmaster_tools.rb +28 -0
  27. data/lib/gdata/client/youtube.rb +47 -0
  28. data/lib/gdata/http.rb +18 -0
  29. data/lib/gdata/http/default_service.rb +82 -0
  30. data/lib/gdata/http/mime_body.rb +95 -0
  31. data/lib/gdata/http/request.rb +74 -0
  32. data/lib/gdata/http/response.rb +44 -0
  33. data/lib/gdata/version.rb +3 -0
  34. data/test/tc_gdata_auth_authsub.rb +54 -0
  35. data/test/tc_gdata_auth_clientlogin.rb +60 -0
  36. data/test/tc_gdata_client_base.rb +38 -0
  37. data/test/tc_gdata_client_calendar.rb +41 -0
  38. data/test/tc_gdata_client_photos.rb +66 -0
  39. data/test/tc_gdata_client_youtube.rb +78 -0
  40. data/test/tc_gdata_http_mime_body.rb +47 -0
  41. data/test/tc_gdata_http_request.rb +37 -0
  42. data/test/test_config.yml.example +7 -0
  43. data/test/test_helper.rb +47 -0
  44. data/test/testimage.jpg +0 -0
  45. data/test/ts_gdata.rb +44 -0
  46. data/test/ts_gdata_auth.rb +26 -0
  47. data/test/ts_gdata_client.rb +30 -0
  48. data/test/ts_gdata_http.rb +25 -0
  49. metadata +129 -0
@@ -0,0 +1,102 @@
1
+ # Copyright (C) 2008 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'cgi'
16
+
17
+ module GData
18
+ module Auth
19
+
20
+ # This class implements ClientLogin signatures for Data API requests.
21
+ # It can be used with a GData::Client::GData object.
22
+ class ClientLogin
23
+
24
+ # The ClientLogin authentication handler
25
+ attr_accessor :auth_url
26
+ # One of 'HOSTED_OR_GOOGLE', 'GOOGLE', or 'HOSTED'.
27
+ # See documentation here:
28
+ # http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html
29
+ attr_accessor :account_type
30
+ # The access token
31
+ attr_accessor :token
32
+ # The service name for the API you are working with
33
+ attr_accessor :service
34
+
35
+ # Initialize the class with the service name of an API that you wish
36
+ # to request a token for.
37
+ def initialize(service, options = {})
38
+ if service.nil?
39
+ raise ArgumentError, "Service name cannot be nil"
40
+ end
41
+
42
+ @service = service
43
+
44
+ options.each do |key, value|
45
+ self.send("#{key}=", value)
46
+ end
47
+
48
+ @auth_url ||= 'https://www.google.com/accounts/ClientLogin'
49
+ @account_type ||= 'HOSTED_OR_GOOGLE'
50
+ end
51
+
52
+ # Retrieves a token for the given username and password.
53
+ # source identifies your application.
54
+ # login_token and login_captcha are used only if you are responding
55
+ # to a previously issued CAPTCHA challenge.
56
+ def get_token(username, password, source, login_token = nil,
57
+ login_captcha = nil)
58
+ body = Hash.new
59
+ body['accountType'] = @account_type
60
+ body['Email'] = username
61
+ body['Passwd'] = password
62
+ body['service'] = @service
63
+ body['source'] = source
64
+ if login_token and login_captcha
65
+ body['logintoken'] = login_token
66
+ body['logincaptcha'] = login_captcha
67
+ end
68
+
69
+ request = GData::HTTP::Request.new(@auth_url, :body => body,
70
+ :method => :post)
71
+ service = GData::HTTP::DefaultService.new
72
+ response = service.make_request(request)
73
+ if response.status_code != 200
74
+ url = response.body[/Url=(.*)/,1]
75
+ error = response.body[/Error=(.*)/,1]
76
+
77
+ if error == "CaptchaRequired"
78
+ captcha_token = response.body[/CaptchaToken=(.*)/,1]
79
+ captcha_url = response.body[/CaptchaUrl=(.*)/,1]
80
+ raise GData::Client::CaptchaError.new(captcha_token, captcha_url),
81
+ "#{error} : #{url}"
82
+ end
83
+
84
+ raise GData::Client::AuthorizationError.new(response)
85
+ end
86
+
87
+ @token = response.body[/Auth=(.*)/,1]
88
+ return @token
89
+ end
90
+
91
+ # Creates an appropriate Authorization header on a GData::HTTP::Request
92
+ # object.
93
+ def sign_request!(request)
94
+ if @token == nil
95
+ raise GData::Client::Error, "Cannot sign request without credentials"
96
+ end
97
+
98
+ request.headers['Authorization'] = "GoogleLogin auth=#{@token}"
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,84 @@
1
+ # Copyright (C) 2008 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'gdata/client/base'
16
+ require 'gdata/client/apps'
17
+ require 'gdata/client/blogger'
18
+ require 'gdata/client/booksearch'
19
+ require 'gdata/client/calendar'
20
+ require 'gdata/client/contacts'
21
+ require 'gdata/client/doclist'
22
+ require 'gdata/client/finance'
23
+ require 'gdata/client/gbase'
24
+ require 'gdata/client/gmail'
25
+ require 'gdata/client/health'
26
+ require 'gdata/client/notebook'
27
+ require 'gdata/client/photos'
28
+ require 'gdata/client/spreadsheets'
29
+ require 'gdata/client/webmaster_tools'
30
+ require 'gdata/client/youtube'
31
+
32
+ module GData
33
+ module Client
34
+
35
+ # Base class for GData::Client errors
36
+ class Error < RuntimeError
37
+ end
38
+
39
+ # Base class for errors raised due to requests
40
+ class RequestError < Error
41
+
42
+ # The Net::HTTPResponse that caused this error.
43
+ attr_accessor :response
44
+
45
+ # Creates a new RequestError from Net::HTTPResponse +response+ with a
46
+ # message containing the error code and response body.
47
+ def initialize(response)
48
+ @response = response
49
+
50
+ super "request error #{response.status_code}: #{response.body}"
51
+ end
52
+
53
+ end
54
+
55
+ class AuthorizationError < RequestError
56
+ end
57
+
58
+ class BadRequestError < RequestError
59
+ end
60
+
61
+ # An error caused by ClientLogin issuing a CAPTCHA error.
62
+ class CaptchaError < RuntimeError
63
+ # The token identifying the CAPTCHA
64
+ attr_reader :token
65
+ # The URL to the CAPTCHA image
66
+ attr_reader :url
67
+
68
+ def initialize(token, url)
69
+ @token = token
70
+ @url = url
71
+ end
72
+ end
73
+
74
+ class ServerError < RequestError
75
+ end
76
+
77
+ class UnknownError < RequestError
78
+ end
79
+
80
+ class VersionConflictError < RequestError
81
+ end
82
+
83
+ end
84
+ end
@@ -0,0 +1,27 @@
1
+ # Copyright (C) 2008 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module GData
16
+ module Client
17
+
18
+ # Client class to wrap working with the Apps Provisioning API.
19
+ class Apps < Base
20
+
21
+ def initialize(options = {})
22
+ options[:clientlogin_service] ||= 'apps'
23
+ super(options)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,182 @@
1
+ # Copyright (C) 2008 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module GData
16
+ module Client
17
+
18
+ # A client object used to interact with different Google Data APIs.
19
+ class Base
20
+
21
+ # A subclass of GData::Auth that handles authentication signing.
22
+ attr_accessor :auth_handler
23
+ # A subclass of GData::HTTP that handles making HTTP requests.
24
+ attr_accessor :http_service
25
+ # Headers to include in every request.
26
+ attr_accessor :headers
27
+ # The API version being used.
28
+ attr_accessor :version
29
+ # The default URL for ClientLogin.
30
+ attr_accessor :clientlogin_url
31
+ # A default service name for ClientLogin (overriden by subclasses).
32
+ attr_accessor :clientlogin_service
33
+ # The broadest AuthSub scope for working with an API.
34
+ # This is overriden by the service-specific subclasses.
35
+ attr_accessor :authsub_scope
36
+ # A short string identifying the current application.
37
+ attr_accessor :source
38
+
39
+ def initialize(options = {})
40
+ options.each do |key, value|
41
+ self.send("#{key}=", value)
42
+ end
43
+
44
+ @headers ||= {}
45
+ @http_service ||= GData::HTTP::DefaultService
46
+ @version ||= '2'
47
+ @source ||= 'AnonymousApp'
48
+ end
49
+
50
+ # Sends an HTTP request with the given file as a stream
51
+ def make_file_request(method, url, file_path, mime_type, entry = nil)
52
+ if not File.readable?(file_path)
53
+ raise ArgumentError, "File #{file_path} is not readable."
54
+ end
55
+ file = File.open(file_path, 'rb')
56
+ @headers['Slug'] = File.basename(file_path)
57
+ if entry
58
+ @headers['MIME-Version'] = '1.0'
59
+ body = GData::HTTP::MimeBody.new(entry, file, mime_type)
60
+ @headers['Content-Type'] = body.content_type
61
+ response = self.make_request(method, url, body)
62
+ else
63
+ @headers['Content-Type'] = mime_type
64
+ response = self.make_request(method, url, file)
65
+ end
66
+ file.close
67
+ return response
68
+ end
69
+
70
+ # Sends an HTTP request and return the response.
71
+ def make_request(method, url, body = '')
72
+ headers = self.prepare_headers
73
+ request = GData::HTTP::Request.new(url, :headers => headers,
74
+ :method => method, :body => body)
75
+
76
+ if @auth_handler and @auth_handler.respond_to?(:sign_request!)
77
+ @auth_handler.sign_request!(request)
78
+ end
79
+
80
+ service = http_service.new
81
+ response = service.make_request(request)
82
+
83
+ case response.status_code
84
+ when 200, 201, 302
85
+ #Do nothing, it's a success.
86
+ when 401, 403
87
+ raise AuthorizationError.new(response)
88
+ when 400
89
+ raise BadRequestError.new(response)
90
+ when 409
91
+ raise VersionConflictError.new(response)
92
+ when 500
93
+ raise ServerError.new(response)
94
+ else
95
+ raise UnknownError.new(response)
96
+ end
97
+
98
+ return response
99
+ end
100
+
101
+ # Performs an HTTP GET against the API.
102
+ def get(url)
103
+ return self.make_request(:get, url)
104
+ end
105
+
106
+ # Performs an HTTP PUT against the API.
107
+ def put(url, body)
108
+ return self.make_request(:put, url, body)
109
+ end
110
+
111
+ # Performs an HTTP PUT with the given file
112
+ def put_file(url, file_path, mime_type, entry = nil)
113
+ return self.make_file_request(:put, url, file_path, mime_type, entry)
114
+ end
115
+
116
+ # Performs an HTTP POST against the API.
117
+ def post(url, body)
118
+ return self.make_request(:post, url, body)
119
+ end
120
+
121
+ # Performs an HTTP POST with the given file
122
+ def post_file(url, file_path, mime_type, entry = nil)
123
+ return self.make_file_request(:post, url, file_path, mime_type, entry)
124
+ end
125
+
126
+ # Performs an HTTP DELETE against the API.
127
+ def delete(url)
128
+ return self.make_request(:delete, url)
129
+ end
130
+
131
+ # Constructs some necessary headers for every request.
132
+ def prepare_headers
133
+ headers = @headers
134
+ headers['GData-Version'] = @version
135
+ headers['User-Agent'] = GData::Auth::SOURCE_LIB_STRING + @source
136
+ # by default we assume we are sending Atom entries
137
+ if not headers.has_key?('Content-Type')
138
+ headers['Content-Type'] = 'application/atom+xml'
139
+ end
140
+ return headers
141
+ end
142
+
143
+ # Performs ClientLogin for the service. See GData::Auth::ClientLogin
144
+ # for details.
145
+ def clientlogin(username, password, captcha_token = nil,
146
+ captcha_answer = nil, service = nil, account_type = nil)
147
+ if service.nil?
148
+ service = @clientlogin_service
149
+ end
150
+ options = { :account_type => account_type }
151
+ self.auth_handler = GData::Auth::ClientLogin.new(service, options)
152
+ if @clientlogin_url
153
+ @auth_handler.auth_url = @clientlogin_url
154
+ end
155
+ source = GData::Auth::SOURCE_LIB_STRING + @source
156
+ @auth_handler.get_token(username, password, source, captcha_token, captcha_answer)
157
+ end
158
+
159
+ def authsub_url(next_url, secure = false, session = true, domain = nil,
160
+ scope = nil)
161
+ if scope.nil?
162
+ scope = @authsub_scope
163
+ end
164
+ GData::Auth::AuthSub.get_url(next_url, scope, secure, session, domain)
165
+ end
166
+
167
+ # Sets an AuthSub token for the service.
168
+ def authsub_token=(token)
169
+ self.auth_handler = GData::Auth::AuthSub.new(token)
170
+ end
171
+
172
+ # Sets a private key to use with AuthSub requests.
173
+ def authsub_private_key=(key)
174
+ if @auth_handler.class == GData::Auth::AuthSub
175
+ @auth_handler.private_key = key
176
+ else
177
+ raise Error, "An AuthSub token must be set first."
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,28 @@
1
+ # Copyright (C) 2008 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module GData
16
+ module Client
17
+
18
+ # Client class to wrap working with the Blogger API.
19
+ class Blogger < Base
20
+
21
+ def initialize(options = {})
22
+ options[:clientlogin_service] ||= 'blogger'
23
+ options[:authsub_scope] ||= 'http://www.blogger.com/feeds/'
24
+ super(options)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ # Copyright (C) 2008 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module GData
16
+ module Client
17
+
18
+ # Client class to wrap working with the Book Search Data API.
19
+ class BookSearch < Base
20
+
21
+ def initialize(options = {})
22
+ options[:clientlogin_service] ||= 'print'
23
+ options[:authsub_scope] ||= 'https://www.google.com/books/feeds/'
24
+ super(options)
25
+ end
26
+ end
27
+ end
28
+ end