intouch-gdata4ruby 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,16 @@
1
+ #=CHANGELOG
2
+ #==version 0.1.6
3
+ #* Save the 'S'-cookie and send it with future requests to avoid '302 Redirect' responses
4
+ #==version 0.1.5
5
+ #* Changed license to LGPLv3
6
+ #==version 0.1.4
7
+ #* Bugfix for GeoRSS and GML namespaces
8
+ #==version 0.1.3
9
+ #* Added support for Geo/GeoRSS namespaces in base gdata object
10
+ #* Added support for Ruby 1.9
11
+ #==version 0.1.2
12
+ #* Added better support for 'default' users in AccessRule
13
+ #==version 0.1.1
14
+ #* Added additional common attributes, including content, published, updated and author info
15
+ #==version 0.1.0
16
+ #* Initial Version
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ #GData4Ruby
2
+
3
+ ##Introduction
4
+
5
+ GData4Ruby is a full featured wrapper for the Google Data base API. GData4Ruby provides the ability
6
+ to authenticate with GData using the ClientLogin method. The package also includes a base gdata object
7
+ that can be subclassed to provide basic CRUD functions for all Google API service objects. Additionally,
8
+ a basic ACL object is included for interacting with ACL feeds and setting access rules.
9
+
10
+ ##Author and Contact Information
11
+
12
+ GData4Ruby was created and is maintained by [Mike Reich](mailto:mike@seabourneconsulting.com])
13
+ and is licenses under the LGPL v3. You can find the text of the LGPL
14
+ here: http://www.gnu.org/licenses/lgpl.html. Feel free to use and update, but be sure to contribute your
15
+ code back to the project and attribute as required by the license.
16
+
17
+ ##Website
18
+
19
+ [http://cookingandcoding.com/gdata4ruby/](http://cookingandcoding.com/gdata4ruby/)
20
+
21
+ ##Description
22
+
23
+ GData4Ruby has three major components: the service, the GData object and the AccessRule object. Each service
24
+ represents a google account, and includes a username (email) and a password. You can use the GData service
25
+ to authenticate either a google account or a google apps account.
26
+
27
+ The GData object provides a base class for interacting with Google API objects, i.e. Documents, Events, etc. The GData object contains common attributes present in all Google API objects, and provides interfaces for basic CRUD functions. This class is meant to be subclassed.
28
+
29
+ The AccessRule object provides a base class for interacting with Google Access Control Lists. ACLs provide the main permissions mechanism for most Google API services.
30
+
31
+ ##Examples
32
+
33
+ Below are some common usage examples. For more examples, check the documentation.
34
+
35
+ ###Service
36
+
37
+ 1. Authenticate
38
+
39
+ service = Service.new
40
+ service.authenticate("user@gmail.com", "password", "cl")
41
+
42
+ 2. Authenticate with a specified GData version
43
+
44
+ service = Service.new({:gdata_version => '3.0'})
45
+ service.authenticate("user@gmail.com", "password", "cl")
data/lib/gdata4ruby.rb ADDED
@@ -0,0 +1 @@
1
+ require "gdata4ruby/service"
@@ -0,0 +1,127 @@
1
+ # Author:: Mike Reich (mike@seabourneconsulting.com)
2
+ # Copyright:: Copyright (C) 2010 Mike Reich
3
+ # License:: GPL v2
4
+ #--
5
+ # Licensed under the General Public License (GPL), Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ #
15
+ # Feel free to use and update, but be sure to contribute your
16
+ # code back to the project and attribute as required by the license.
17
+ #++
18
+ require 'gdata4ruby/gdata_object'
19
+
20
+ module GData4Ruby
21
+
22
+ #Contains classes for interacting with Google ACL feeds
23
+ module ACL
24
+
25
+ #Represents an individual access rule entry in a Google ACL feed.
26
+ class AccessRule < GDataObject
27
+ XML = "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gAcl='http://schemas.google.com/acl/2007'>
28
+ <category scheme='http://schemas.google.com/g/2005#kind'
29
+ term='http://schemas.google.com/acl/2007#accessRule'/>
30
+ <gAcl:role value=''/>
31
+ <gAcl:scope type='user' value=''/>
32
+ </entry>"
33
+
34
+ #The Rule's user
35
+ attr_accessor :user
36
+
37
+ #The user's role
38
+ attr_accessor :role
39
+
40
+ #The parent GDataObject the rule applies to
41
+ attr_accessor :parent
42
+
43
+ #Creates a new AccessRule object. You must pass a valid Service and GDataObject, and can pass an optional hash
44
+ #of attributes to initialize the object with.
45
+ def initialize(service, parent, attributes = {})
46
+ super(service, attributes)
47
+ @xml = XML
48
+ raise ArgumentError, 'parent must be a GData4Ruby::GDataObject' if not parent.is_a? GData4Ruby::GDataObject
49
+ @parent = parent
50
+ @role = @user = nil
51
+ end
52
+
53
+ #Creates the AccessRule using the parent's acl_uri attribute.
54
+ def create
55
+ ret = service.send_request(Request.new(:post, @parent.acl_uri, to_xml))
56
+ if not ret or not load(ret.body)
57
+ raise SaveFailed, 'Could not create access rule'
58
+ end
59
+ return ret
60
+ end
61
+
62
+ #Loads data into the object. Accepts a string containing an XML <entry> object.
63
+ def load(string)
64
+ super(string)
65
+ @folders = []
66
+ xml = REXML::Document.new(string)
67
+ xml.root.elements.each(){}.map do |ele|
68
+ case ele.name
69
+ when 'role'
70
+ @role = ele.attributes['value']
71
+ when 'scope'
72
+ @user = ele.attributes['value'] ? ele.attributes['value'] : ele.attributes['type']
73
+ end
74
+ end
75
+ end
76
+
77
+ #Deletes the AccessRule
78
+ def delete
79
+ if @exists
80
+ @role = 'none'
81
+ service.send_request(Request.new(:put, @edit_uri, self.to_xml, {"If-Match" => "*", 'Content-Type' => 'application/atom+xml'}))
82
+ end
83
+ @exists = false
84
+ return true
85
+ end
86
+
87
+ #Finds an AccessRule based on the args passed.
88
+ #
89
+ #Args can be a hash containing either:
90
+ #*user*:: an email address/user id to search for. If found, returns the matching AccessRule object.
91
+ #*role*:: the role to search for. Returns an array of matching AccessRules, or an empty array if no matches are found.
92
+ def self.find(service, parent, args = {})
93
+ raise ArgumentError, 'Must supply a username or role to find by' if not args[:user] and not args[:role]
94
+ rules = []
95
+ ret = service.send_request(GData4Ruby::Request.new(:get, parent.acl_uri))
96
+ xml = REXML::Document.new(ret.body).root
97
+ xml.elements.each("entry") do |e|
98
+ e = GData4Ruby::Utils::add_namespaces(e)
99
+ rule = AccessRule.new(service, parent)
100
+ rule.load(e.to_s)
101
+ return rule if args[:user] and rule.user == args[:user]
102
+ rules << rule if args[:role] and rule.role == args[:role]
103
+ end
104
+ return args[:user] ? false : rules
105
+ end
106
+
107
+ #Returns a string containing the XML representation of the AccessRule
108
+ def to_xml
109
+ xml = REXML::Document.new(super)
110
+ xml.root.elements.each(){}.map do |ele|
111
+ case ele.name
112
+ when "role"
113
+ ele.attributes['value'] = @role
114
+ when 'scope'
115
+ if @user and @user != 'default'
116
+ ele.attributes['value'] = @user
117
+ else
118
+ ele.attributes['type'] = 'default'
119
+ ele.delete_attribute("value")
120
+ end
121
+ end
122
+ end
123
+ xml.to_s
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,213 @@
1
+ # Author:: Mike Reich (mike@seabourneconsulting.com)
2
+ # Copyright:: Copyright (C) 2010 Mike Reich
3
+ # License:: GPL v2
4
+ #--
5
+ # Licensed under the General Public License (GPL), Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ #
15
+ # Feel free to use and update, but be sure to contribute your
16
+ # code back to the project and attribute as required by the license.
17
+ #++
18
+
19
+ require "net/http"
20
+ require "net/https"
21
+ require 'time'
22
+ require 'cgi'
23
+ require 'gdata4ruby/request'
24
+ require 'gdata4ruby/utils/utils'
25
+ require 'rexml/document'
26
+
27
+ Net::HTTP.version_1_2
28
+
29
+ # GData4Ruby is a full featured wrapper for the base google data API
30
+
31
+ module GData4Ruby
32
+
33
+ class AuthenticationFailed < StandardError; end #:nodoc: all
34
+
35
+ class NotAuthenticated < StandardError; end
36
+
37
+ class InvalidService < StandardError; end
38
+
39
+ class HTTPRequestFailed < StandardError; end
40
+
41
+ class QueryParameterError < StandardError; end
42
+
43
+ #The ProxyInfo class contains information for configuring a proxy connection
44
+
45
+ class ProxyInfo
46
+ attr_accessor :address, :port, :username, :password
47
+ @address = nil
48
+ @port = nil
49
+ @username = nil
50
+ @password = nil
51
+
52
+ #The initialize function accepts four variables for configuring the ProxyInfo object.
53
+ #The proxy connection is initiated using the builtin Net::HTTP proxy support.
54
+
55
+ def initialize(address, port, username=nil, password=nil)
56
+ @address = address
57
+ @port = port
58
+ @username = username
59
+ @password = password
60
+ end
61
+ end
62
+
63
+ #The Base class includes the basic HTTP methods for communicating with the Google Data API.
64
+ #You shouldn't use this class directly, rather access the functionality through
65
+ #the Service subclass.
66
+
67
+ class Base
68
+ AUTH_URL = "https://www.google.com/accounts/ClientLogin"
69
+ @proxy_info = nil
70
+ @auth_token = nil
71
+ @debug = false
72
+ @gdata_version = '2.1'
73
+ @session_cookie = nil
74
+
75
+ #Contains the ProxyInfo object for using a proxy server
76
+ attr_accessor :proxy_info
77
+
78
+ #If set to true, debug will dump all raw HTTP requests and responses
79
+ attr_accessor :debug
80
+
81
+ #The GData version used by the service
82
+ attr_accessor :gdata_version
83
+
84
+ # Will have the service use https instead of http
85
+ attr_accessor :use_ssl
86
+
87
+ #Optionally, pass a hash of attributes to populate the class. If you want to use a GData version
88
+ #other than the default (2.1), pass a key/value pair, i.e. {:gdata_version => '1.0'}
89
+ def initialize(attributes = {})
90
+ attributes.each do |key, value|
91
+ if self.respond_to?("#{key}=")
92
+ self.send("#{key}=", value)
93
+ end
94
+ end
95
+ @gdata_version = attributes[:gdata_version] ? attributes[:gdata_version] : '2.1'
96
+ @use_ssl ||= false
97
+ end
98
+
99
+ def create_url(path)
100
+ return http_protocol + path
101
+ end
102
+
103
+ #Sends a request to the Google Data System. Accepts a valid Request object, and returns a
104
+ #HTTPResult class.
105
+ def send_request(request)
106
+ raise ArgumentError 'Request must be a GData4Ruby::Request object' if not request.is_a?Request
107
+ puts "sending #{request.type} to url = #{request.url.to_s}" if @debug
108
+ do_request(request)
109
+ end
110
+
111
+ private
112
+
113
+ def set_protocol!(request)
114
+ uri = request.url
115
+ if uri.scheme != protocol
116
+ request.url = URI.parse(uri.to_s.sub(uri.scheme, protocol))
117
+ # values = uri.select(*uri.component)
118
+ # keys = uri.component
119
+ # components_hash = {}
120
+ # # Build a hash where the keys are from keys[] and values are from values[]
121
+ # keys.zip(values) {|a,b| components_hash[a] = b }
122
+ # components_hash[:scheme] = protocol
123
+ # request.url = case protocol
124
+ # when 'https'
125
+ # URI::HTTPS.build(components_hash)
126
+ # when 'http'
127
+ # URI::HTTP.build(components_hash)
128
+ # end
129
+ end
130
+ end
131
+
132
+ def do_request(request)
133
+ ret = nil
134
+ add_auth_header(request)
135
+ set_protocol!(request)
136
+ # Add the session cookie if available
137
+ request.headers.merge!({'Cookie' => @session_cookie}) if @session_cookie
138
+ http = get_http_object(request.url)
139
+ puts "Sending request\nHeader: #{request.headers.inspect.to_s}\nContent: #{request.content.to_s}\n" if @debug
140
+ http.start do |ht|
141
+ ret = case request.type
142
+ when :get
143
+ ht.get(request.url.to_s, request.headers)
144
+ when :post
145
+ ht.post(request.url.to_s, request.content, request.headers)
146
+ when :put
147
+ ht.put(request.url.to_s, request.content, request.headers)
148
+ when :delete
149
+ ht.delete(request.url.to_s, request.headers)
150
+ end
151
+ end
152
+
153
+ if @debug
154
+ puts "Response code: #{ret.status}"
155
+ puts "Headers: \n"
156
+ ret.headers.each { |h, v| puts "#{h}:#{v}" }
157
+ puts "Body: \n" + ret.body
158
+ end
159
+
160
+ # Save the session cookie if set
161
+ ret.get_fields('set-cookie').to_a.each do |header|
162
+ cookie = header.split(';').first
163
+ @session_cookie = cookie if cookie =~ /^S=.+/
164
+ end
165
+
166
+ if not ret.success?
167
+ puts "invalid response received: "+ret.status if @debug
168
+ raise HTTPRequestFailed, ret.body
169
+ end
170
+ return ret
171
+ end
172
+
173
+ def get_http_object(location)
174
+ if @proxy_info and @proxy_info.address
175
+ http = Net::HTTP.new(location.host, location.port, @proxy_info.address, @proxy_info.port, @proxy_info.username, @proxy_info.password)
176
+ else
177
+ http = Net::HTTP.new(location.host, location.port)
178
+ end
179
+ if location.scheme == 'https'
180
+ #fixed http/http misnaming via JohnMetta
181
+ puts "SSL True" if @debug
182
+ http.use_ssl = true
183
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
184
+ end
185
+ return http
186
+ end
187
+
188
+ def add_auth_header(request)
189
+ if @auth_token
190
+ if request.headers
191
+ request.headers.merge!({'Authorization' => "GoogleLogin auth=#{@auth_token}", "GData-Version" => @gdata_version})
192
+ else
193
+ content_type = (request.type == :get or request.type == :delete) ? 'application/x-www-form-urlencoded' : 'application/atom+xml'
194
+ request.headers = {'Authorization' => "GoogleLogin auth=#{@auth_token}", "GData-Version" => @gdata_version, 'Content-Type' => content_type}
195
+ end
196
+ end
197
+ end
198
+
199
+ protected
200
+
201
+ def protocol
202
+ ssl_suffix = ""
203
+ ssl_suffix = "s" if use_ssl
204
+ return "http#{ssl_suffix}"
205
+ end
206
+
207
+ def http_protocol
208
+ ssl_suffix = ""
209
+ ssl_suffix = "s" if use_ssl
210
+ return "http#{ssl_suffix}://"
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,197 @@
1
+ # Author:: Mike Reich (mike@seabourneconsulting.com)
2
+ # Copyright:: Copyright (C) 2010 Mike Reich
3
+ # License:: GPL v2
4
+ #--
5
+ # Licensed under the General Public License (GPL), Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ #
15
+ # Feel free to use and update, but be sure to contribute your
16
+ # code back to the project and attribute as required by the license.
17
+ #++
18
+
19
+ require 'gdata4ruby/service'
20
+ require 'time'
21
+
22
+ module GData4Ruby
23
+ #The GDataObject class represents any <entry> object returned by a Google Service. Includes
24
+ #attributes for accessing the common elements/parameters of the object, and methods for CRUD
25
+ #operations.
26
+ class GDataObject
27
+ #A Service object
28
+ attr_accessor :service
29
+
30
+ #The entry title.
31
+ attr_accessor :title
32
+
33
+ #The raw date the document was published
34
+ attr_reader :published
35
+
36
+ #The raw date the document was last updated
37
+ attr_reader :updated
38
+
39
+ #The author/owner name
40
+ attr_reader :author_name
41
+
42
+ #The author/owner email
43
+ attr_reader :author_email
44
+
45
+ #The current instance etag for the entry
46
+ attr_reader :etag
47
+
48
+ #The parent URI, if any
49
+ attr_reader :parent_uri
50
+
51
+ #The edit URI, for making changes to the entry
52
+ attr_reader :edit_uri
53
+
54
+ #A hash of additional feedLinks
55
+ attr_reader :feed_links
56
+
57
+ #The unique entry id, as represented by the <gd:resourceId> tag. Not to be confused
58
+ #with the Atom <id> tag, which is accessible as the feed_uri attribute.
59
+ attr_reader :id
60
+
61
+ #The entry's feed uri, otherwise known as the Atom <id> element value.
62
+ attr_reader :feed_uri
63
+
64
+ #A hash of categories
65
+ attr_reader :categories
66
+
67
+ #The feedLink that represents the entry's ACL feed.
68
+ attr_reader :acl_uri
69
+
70
+ #The content uri for exporting the object content
71
+ attr_reader :content_uri
72
+
73
+ #The kind (type) of the object
74
+ attr_reader :kind
75
+
76
+ #Indicates whether the object exists on the Google servers, i.e. has been created/saved.
77
+ def exists?
78
+ return @exists
79
+ end
80
+
81
+ #Initializes a new GDataObject. You must pass a valid Service object, and can pass
82
+ #an optional array of attributes to initialize values. To load data into an object,
83
+ #use the load method.
84
+ def initialize(service, attributes = {})
85
+ @xml ||= ''
86
+ @service ||= service
87
+ @exists = false
88
+ @title = @content_uri = @etag = @acl_uri = @edit_uri = @parent_uri = @feed_uri = @kind = nil
89
+ @categories = @feed_links = []
90
+ @include_etag = true
91
+ attributes.each do |key, value|
92
+ self.send("#{key}=", value)
93
+ end
94
+ end
95
+
96
+ public
97
+ #Loads data into the object. Accepts a string containing an XML <entry> from a GData
98
+ #compliant feed.
99
+ def load(string)
100
+ @exists = @include_etag = true
101
+ @xml = string
102
+ xml = REXML::Document.new(string)
103
+ xml.root.elements.each(){}.map do |ele|
104
+ @etag = xml.root.attributes['etag'] if xml.root.attributes['etag']
105
+ case ele.name
106
+ when "id"
107
+ puts 'setting id' if service.debug
108
+ @feed_uri = ele.text
109
+ when 'content'
110
+ @content_uri = ele.attributes['src'] if ele.attributes['src']
111
+ when 'resourceId'
112
+ @id = ele.text
113
+ when 'title'
114
+ @title = ele.text
115
+ when 'category'
116
+ @categories << {:label => ele.attributes['label'],
117
+ :scheme => ele.attributes['scheme'],
118
+ :term => ele.attributes['term']}
119
+ if ele.attributes['scheme'] and ele.attributes['scheme'] == 'http://schemas.google.com/g/2005#kind'
120
+ @kind = if ele.attributes['label']
121
+ ele.attributes['label']
122
+ else
123
+ ele.attributes['term']
124
+ end
125
+ end
126
+ when 'link'
127
+ case ele.attributes['rel']
128
+ when 'http://schemas.google.com/docs/2007#parent'
129
+ @parent_uri = ele.attributes['href']
130
+ when 'edit'
131
+ @edit_uri = ele.attributes['href']
132
+ when 'http://schemas.google.com/acl/2007#accessControlList'
133
+ @acl_uri = ele.attributes['href'] if not @acl_uri
134
+ end
135
+ when 'feedLink'
136
+ @feed_links << {:rel => ele.attributes['rel'], :href => ele.attributes['href']}
137
+ @acl_uri = ele.attributes['href'] if ele.attributes['rel'].include? 'accessControlList' and not @acl_uri
138
+ when 'author'
139
+ ele.elements.each('name'){}.map {|e| @author_name = e.text}
140
+ ele.elements.each('email'){}.map {|e| @author_email = e.text}
141
+ when 'published'
142
+ @published = Time.parse(ele.text) rescue nil
143
+ when 'updated'
144
+ @updated = Time.parse(ele.text) rescue nil
145
+ end
146
+ end
147
+ return xml.root
148
+ end
149
+
150
+ #Saves the object if it exsits, otherwise creates it.
151
+ def save
152
+ if @exists
153
+ ret = service.send_request(Request.new(:put, @edit_uri, to_xml))
154
+ else
155
+ ret = create
156
+ end
157
+ if not ret or not load(ret.body)
158
+ raise SaveFailed, 'Could not save object'
159
+ end
160
+ return true
161
+ end
162
+
163
+ #Creates the object. This must be overridden in a subclass, as the feed url for creating new
164
+ #objects/entries is service dependent. In other words, each google service uses a different
165
+ #URI for saving new objects.
166
+ def create
167
+ return false
168
+ end
169
+
170
+ #Deletes the object.
171
+ def delete
172
+ if @exists
173
+ service.send_request(Request.new(:delete, @edit_uri, nil, {"If-Match" => "*"}))
174
+ end
175
+ @exists = false
176
+ return true
177
+ end
178
+
179
+ #Creates a new string containing the XML representation of the object as a GData compliant <entry>
180
+ #element.
181
+ def to_xml
182
+ xml = REXML::Document.new(@xml)
183
+ xml.root.elements.each(){}.map do |ele|
184
+ if @include_etag
185
+ xml.root.attributes['gd:etag'] = @etag if @etag and @etag != ''
186
+ else
187
+ xml.root.delete_attribute('gd:etag')
188
+ end
189
+ case ele.name
190
+ when "title"
191
+ ele.text = @title
192
+ end
193
+ end
194
+ xml.to_s
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,61 @@
1
+ # Author:: Mike Reich (mike@seabourneconsulting.com)
2
+ # Copyright:: Copyright (C) 2010 Mike Reich
3
+ # License:: GPL v2
4
+ #--
5
+ # Licensed under the General Public License (GPL), Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ #
15
+ # Feel free to use and update, but be sure to contribute your
16
+ # code back to the project and attribute as required by the license.
17
+ #++
18
+ require "uri"
19
+
20
+ module GData4Ruby
21
+ #The Request class holds all information needed to make a Request to a Google service.
22
+ class Request
23
+ #The HTTP request type, must be one of :get, :post, :put, :delete
24
+ attr_accessor :type
25
+
26
+ #The HTTP request content, only valid for :put and :post requests
27
+ attr_accessor :content
28
+
29
+ #Optional. Additional headers to pass with the request.
30
+ attr_accessor :headers
31
+
32
+ #Optional. Additional query parameters (i.e. "?param=value") to append to the request url
33
+ attr_reader :parameters
34
+
35
+ #Creates a new request object.
36
+ def initialize(type, url, content = nil, headers = nil, query_parameters = nil)
37
+ @parameters = nil
38
+ @headers = headers
39
+ @content = content
40
+ @type = type
41
+ @url = URI.parse(url)
42
+ self.parameters = query_parameters
43
+ end
44
+
45
+ #The HTTP url to send the request to
46
+ def url=(new_url)
47
+ @url = new_url
48
+ end
49
+
50
+ #A hash of additional query parameters (i.e. {'param' => 'value') to append to the request url
51
+ def parameters=(query_parameters)
52
+ raise ArgumentError, 'Query parameters must be a Hash' if query_parameters != nil and not query_parameters.is_a? Hash
53
+ @parameters = query_parameters.is_a?(Hash) ? "?#{query_parameters.to_a.collect{|a| a.join("=")}.join("&")}" : nil
54
+ end
55
+
56
+ #The HTTP url to send the request to
57
+ def url
58
+ return URI.parse("#{@url+(@parameters ? @parameters : '')}")
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,58 @@
1
+ # Author:: Mike Reich (mike@seabourneconsulting.com)
2
+ # Copyright:: Copyright (C) 2010 Mike Reich
3
+ # License:: GPL v2
4
+ #--
5
+ # Licensed under the General Public License (GPL), Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ #
15
+ # Feel free to use and update, but be sure to contribute your
16
+ # code back to the project and attribute as required by the license.
17
+ #++
18
+ require 'gdata4ruby/base'
19
+
20
+ module GData4Ruby
21
+ #The service class is the main handler for all direct interactions with the
22
+ #Google Data API.
23
+
24
+ class Service < Base
25
+ #Convenience attribute contains the currently authenticated account name
26
+ attr_reader :account
27
+
28
+ # The token returned by the Google servers, used to authorize all subsequent messages
29
+ attr_reader :auth_token
30
+
31
+ #Accepts an optional attributes hash for initialization values, most likely :gdata_version
32
+ def initialize(attributes = {})
33
+ super(attributes)
34
+ attributes.each do |key, value|
35
+ self.send("#{key}=", value)
36
+ end
37
+ end
38
+
39
+ # The authenticate method passes the username and password to google servers.
40
+ # If authentication succeeds, returns true, otherwise raises the AuthenticationFailed error.
41
+ # Thanks to David King and Scott Taylor for Ruby 1.9 fix.
42
+ def authenticate(username, password, service)
43
+ @auth_token = nil
44
+ ret = nil
45
+ ret = send_request(Request.new(:post, AUTH_URL, "Email=#{username}&Passwd=#{password}&source=GCal4Ruby&service=#{service}&accountType=HOSTED_OR_GOOGLE"))
46
+ if ret.class == Net::HTTPOK
47
+ body = ret.read_body
48
+ lines = body.send(body.respond_to?(:lines) ? :lines : :to_s).to_a
49
+ @auth_token = lines.to_a[2].gsub("Auth=", "").strip
50
+ @account = username
51
+ @password = password
52
+ return true
53
+ else
54
+ raise AuthenticationFailed
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,35 @@
1
+ # Author:: Mike Reich (mike@seabourneconsulting.com)
2
+ # Copyright:: Copyright (C) 2010 Mike Reich
3
+ # License:: GPL v2
4
+ #--
5
+ # Licensed under the General Public License (GPL), Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ #
15
+ # Feel free to use and update, but be sure to contribute your
16
+ # code back to the project and attribute as required by the license.
17
+ #++
18
+ module GData4Ruby
19
+ #A helper class that includes commonly used utility methods.
20
+ class Utils
21
+ #Adds common Google namespaces to an element. Useful for processing individual events returned from in a feed.
22
+ def self.add_namespaces(entry)
23
+ entry.attributes["xmlns:openSearch"] = "http://a9.com/-/spec/opensearch/1.1/"
24
+ entry.attributes["xmlns:gAcl"] = "http://schemas.google.com/acl/2007"
25
+ entry.attributes["xmlns:gCal"] = "http://schemas.google.com/gCal/2005"
26
+ entry.attributes["xmlns:gd"] = "http://schemas.google.com/g/2005"
27
+ entry.attributes["xmlns:app"] = "http://www.w3.org/2007/app"
28
+ entry.attributes["xmlns:docs"] = "http://schemas.google.com/docs/2007"
29
+ entry.attributes["xmlns"] = "http://www.w3.org/2005/Atom"
30
+ entry.attributes["xmlns:georss"] = "http://www.georss.org/georss"
31
+ entry.attributes["xmlns:gml"] = "http://www.opengis.net/gml"
32
+ entry
33
+ end
34
+ end
35
+ end
data/test/unit.rb ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'rubygems'
4
+ require 'gdata4ruby'
5
+ include GData4Ruby
6
+
7
+ @service = Service.new
8
+ @username = nil
9
+ @password = nil
10
+
11
+ def tester
12
+ if ARGV.include?("-d")
13
+ @service.debug = true
14
+ end
15
+ ARGV.each do |ar|
16
+ if ar.match("username=")
17
+ @username = ar.gsub("username=", "")
18
+ end
19
+ if ar.match("password=")
20
+ @password = ar.gsub("password=", "")
21
+ end
22
+ end
23
+ service_test
24
+ end
25
+
26
+ def service_test
27
+ puts "---Starting Service Test---"
28
+ puts "1. Authenticate"
29
+ if @service.authenticate(@username, @password, 'cl')
30
+ successful
31
+ else
32
+ failed
33
+ end
34
+
35
+ puts "2. Authenticate with GData version 3.0"
36
+ @service = Service.new({:gdata_version => '3.0'})
37
+ if @service.authenticate(@username, @password, 'cl') and @service.gdata_version == '3.0'
38
+ successful
39
+ else
40
+ failed
41
+ end
42
+ end
43
+
44
+ def failed(m = nil)
45
+ puts "Test Failed"
46
+ puts m if m
47
+ exit()
48
+ end
49
+
50
+ def successful(m = nil)
51
+ puts "Test Successful"
52
+ puts m if m
53
+ end
54
+
55
+ tester
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: intouch-gdata4ruby
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.5
6
+ platform: ruby
7
+ authors:
8
+ - Mike Reich
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-04-29 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: oauth2
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.4.1
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ description: A full featured wrapper for interacting with the base Google Data API, including authentication and basic object handling
27
+ email: mike@seabourneconsulting.com
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files: []
33
+
34
+ files:
35
+ - README.md
36
+ - CHANGELOG
37
+ - lib/gdata4ruby.rb
38
+ - lib/gdata4ruby/base.rb
39
+ - lib/gdata4ruby/service.rb
40
+ - lib/gdata4ruby/request.rb
41
+ - lib/gdata4ruby/gdata_object.rb
42
+ - lib/gdata4ruby/utils/utils.rb
43
+ - lib/gdata4ruby/acl/access_rule.rb
44
+ - test/unit.rb
45
+ homepage: http://cookingandcoding.com/gdata4ruby/
46
+ licenses: []
47
+
48
+ post_install_message:
49
+ rdoc_options: []
50
+
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ requirements: []
66
+
67
+ rubyforge_project: gdata4ruby
68
+ rubygems_version: 1.7.2
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: A full featured wrapper for interacting with the base Google Data API
72
+ test_files:
73
+ - test/unit.rb