go-picasa-go 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +135 -0
- data/Rakefile +16 -0
- data/TODO +10 -0
- data/VERSION +1 -0
- data/bin/go-picasa-go +64 -0
- data/examples/rails-example/README +243 -0
- data/examples/rails-example/Rakefile +10 -0
- data/examples/rails-example/app/controllers/albums_controller.rb +62 -0
- data/examples/rails-example/app/controllers/application_controller.rb +10 -0
- data/examples/rails-example/app/controllers/photos_controller.rb +77 -0
- data/examples/rails-example/app/helpers/albums_helper.rb +9 -0
- data/examples/rails-example/app/helpers/application_helper.rb +3 -0
- data/examples/rails-example/app/models/my_user.rb +9 -0
- data/examples/rails-example/app/views/albums/_form.html.erb +15 -0
- data/examples/rails-example/app/views/albums/edit.html.erb +10 -0
- data/examples/rails-example/app/views/albums/index.html.erb +50 -0
- data/examples/rails-example/app/views/albums/new.html.erb +10 -0
- data/examples/rails-example/app/views/photos/index.html.erb +30 -0
- data/examples/rails-example/app/views/photos/new.html.erb +8 -0
- data/examples/rails-example/app/views/photos/show.html.erb +19 -0
- data/examples/rails-example/config/boot.rb +110 -0
- data/examples/rails-example/config/database.yml +22 -0
- data/examples/rails-example/config/environment.rb +42 -0
- data/examples/rails-example/config/environments/development.rb +17 -0
- data/examples/rails-example/config/environments/production.rb +28 -0
- data/examples/rails-example/config/environments/test.rb +28 -0
- data/examples/rails-example/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/rails-example/config/initializers/inflections.rb +10 -0
- data/examples/rails-example/config/initializers/mime_types.rb +5 -0
- data/examples/rails-example/config/initializers/new_rails_defaults.rb +21 -0
- data/examples/rails-example/config/initializers/session_store.rb +15 -0
- data/examples/rails-example/config/locales/en.yml +5 -0
- data/examples/rails-example/config/routes.rb +49 -0
- data/examples/rails-example/db/seeds.rb +7 -0
- data/examples/rails-example/doc/README_FOR_APP +2 -0
- data/examples/rails-example/log/development.log +6923 -0
- data/examples/rails-example/log/production.log +0 -0
- data/examples/rails-example/log/server.log +0 -0
- data/examples/rails-example/log/test.log +0 -0
- data/examples/rails-example/public/404.html +30 -0
- data/examples/rails-example/public/422.html +30 -0
- data/examples/rails-example/public/500.html +30 -0
- data/examples/rails-example/public/favicon.ico +0 -0
- data/examples/rails-example/public/images/rails.png +0 -0
- data/examples/rails-example/public/index.html +275 -0
- data/examples/rails-example/public/javascripts/application.js +2 -0
- data/examples/rails-example/public/javascripts/controls.js +963 -0
- data/examples/rails-example/public/javascripts/dragdrop.js +973 -0
- data/examples/rails-example/public/javascripts/effects.js +1128 -0
- data/examples/rails-example/public/javascripts/prototype.js +4320 -0
- data/examples/rails-example/public/robots.txt +5 -0
- data/examples/rails-example/script/about +4 -0
- data/examples/rails-example/script/console +3 -0
- data/examples/rails-example/script/dbconsole +3 -0
- data/examples/rails-example/script/destroy +3 -0
- data/examples/rails-example/script/generate +3 -0
- data/examples/rails-example/script/performance/benchmarker +3 -0
- data/examples/rails-example/script/performance/profiler +3 -0
- data/examples/rails-example/script/plugin +3 -0
- data/examples/rails-example/script/runner +3 -0
- data/examples/rails-example/script/server +3 -0
- data/examples/rails-example/test/functional/albums_controller_test.rb +8 -0
- data/examples/rails-example/test/performance/browsing_test.rb +9 -0
- data/examples/rails-example/test/test_helper.rb +38 -0
- data/examples/rails-example/test/unit/helpers/albums_helper_test.rb +4 -0
- data/go_picasa_go.gemspec +184 -0
- data/init.rb +1 -0
- data/lib/generators/authentication_token_generator.rb +12 -0
- data/lib/generators/template/user_class.erb +9 -0
- data/lib/generators/user_class_generator.rb +50 -0
- data/lib/go_picasa_go.rb +26 -0
- data/lib/patchs/object.rb +21 -0
- data/lib/patchs/ssl.rb +9 -0
- data/lib/picasa/album.rb +267 -0
- data/lib/picasa/authentication.rb +19 -0
- data/lib/picasa/default_album.rb +9 -0
- data/lib/picasa/default_photo.rb +6 -0
- data/lib/picasa/default_user.rb +6 -0
- data/lib/picasa/http/album.rb +113 -0
- data/lib/picasa/http/authentication.rb +40 -0
- data/lib/picasa/http/photo.rb +117 -0
- data/lib/picasa/missing.rb +22 -0
- data/lib/picasa/photo.rb +190 -0
- data/lib/picasa/template/album.xml.erb +20 -0
- data/lib/picasa/template/photo.erb +15 -0
- data/lib/picasa/user.rb +57 -0
- data/lib/picasa/util.rb +33 -0
- data/script.rb +46 -0
- data/spec/album_spec.rb +245 -0
- data/spec/authentication_spec.rb +19 -0
- data/spec/default_classes_spec.rb +50 -0
- data/spec/fixture/photo.jpg +0 -0
- data/spec/fixture/photo2.jpg +0 -0
- data/spec/generators/user_class_generator_spec.rb +40 -0
- data/spec/http/album_spec.rb +129 -0
- data/spec/http/authentication_spec.rb +15 -0
- data/spec/http/photo_spec.rb +78 -0
- data/spec/http_response_helper.rb +23 -0
- data/spec/mock_helper.rb +113 -0
- data/spec/photo_spec.rb +201 -0
- data/spec/spec_helper.rb +151 -0
- data/spec/suites/all.rb +14 -0
- data/spec/suites/all_mocked.rb +5 -0
- data/spec/user_spec.rb +74 -0
- metadata +222 -0
data/lib/picasa/album.rb
ADDED
@@ -0,0 +1,267 @@
|
|
1
|
+
# Module that offers methods to do high level operations concerning
|
2
|
+
# a album within Picasa.
|
3
|
+
|
4
|
+
module Picasa::Album
|
5
|
+
|
6
|
+
include Picasa::Missing
|
7
|
+
|
8
|
+
# Class methods to be added to the class that will include this module.
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
include Picasa::Util
|
12
|
+
|
13
|
+
# Sets the user class configured so it can be used later.
|
14
|
+
|
15
|
+
def belongs_to_picasa_user params
|
16
|
+
unless params[:class_name] and params[:class_name].class == String
|
17
|
+
raise Exception, 'You should pass the string of the class name that includes Picasa::User.'
|
18
|
+
end
|
19
|
+
|
20
|
+
define_dependent_class_methods :user_class, params[:class_name]
|
21
|
+
end
|
22
|
+
|
23
|
+
# Method used to tell the gem what is the class that implements the
|
24
|
+
# Picasa::Photo module.
|
25
|
+
|
26
|
+
def has_many_picasa_photos params
|
27
|
+
unless params[:class_name] and params[:class_name].class == String
|
28
|
+
raise Exception, 'You should pass the string of the class name that includes Picasa::Album.'
|
29
|
+
end
|
30
|
+
|
31
|
+
define_dependent_class_methods :photo_class, params[:class_name]
|
32
|
+
end
|
33
|
+
|
34
|
+
# Find an album by user_id and album_id. It's mandatory to inform the
|
35
|
+
# authentication token. If no album is found, then an exception is raised.
|
36
|
+
|
37
|
+
def picasa_find user_id, album_id, auth_token
|
38
|
+
resp, data = Picasa::HTTP::Album.get_album user_id, album_id, auth_token
|
39
|
+
|
40
|
+
if resp.code != "200" or resp.message != "OK"
|
41
|
+
return nil
|
42
|
+
end
|
43
|
+
|
44
|
+
album = new
|
45
|
+
album.send(:populate_attributes_from_xml, data)
|
46
|
+
album.user = create_user user_id, auth_token
|
47
|
+
album
|
48
|
+
end
|
49
|
+
|
50
|
+
# Find an album by user_id and album_id. It's mandatory to inform the
|
51
|
+
# authentication token. If no album is found, then an exception is raised.
|
52
|
+
|
53
|
+
def picasa_find_all user_id, auth_token
|
54
|
+
albums = []
|
55
|
+
resp, data = Picasa::HTTP::Album.get_albums user_id, auth_token
|
56
|
+
|
57
|
+
if resp.code != "200" or resp.message != "OK"
|
58
|
+
return nil
|
59
|
+
end
|
60
|
+
|
61
|
+
doc = Nokogiri::XML(data)
|
62
|
+
doc.css('entry').each do |entry|
|
63
|
+
album = new
|
64
|
+
album.send(:populate_attributes, entry)
|
65
|
+
album.user = create_user user_id, auth_token
|
66
|
+
albums << album
|
67
|
+
end
|
68
|
+
albums
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def create_user picasa_id, auth_token
|
74
|
+
user = user_class.new
|
75
|
+
user.picasa_id = picasa_id
|
76
|
+
user.auth_token = auth_token
|
77
|
+
user
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.included(base)
|
82
|
+
base.extend(ClassMethods)
|
83
|
+
end
|
84
|
+
|
85
|
+
attr_reader :picasa_id, :author_name, :author_uri, :timestamp, :num_photos,
|
86
|
+
:nickname, :commenting_enable, :comment_count,
|
87
|
+
:media_content_url, :media_thumbnail_url, :user, :link_edit
|
88
|
+
|
89
|
+
attr_accessor :title, :summary, :location, :keywords, :user, :access
|
90
|
+
|
91
|
+
alias_method :cover_url, :media_content_url
|
92
|
+
alias_method :thumbnail_url, :media_thumbnail_url
|
93
|
+
|
94
|
+
# Post an album into Picasa.
|
95
|
+
# If cannot create the album an exception is raised.
|
96
|
+
|
97
|
+
def picasa_save!
|
98
|
+
if self.picasa_id and picasa_id.length > 0
|
99
|
+
return self.picasa_update!
|
100
|
+
end
|
101
|
+
|
102
|
+
params = {
|
103
|
+
:title => title,
|
104
|
+
:summary => summary,
|
105
|
+
:location => location,
|
106
|
+
:keywords => keywords,
|
107
|
+
:access => access
|
108
|
+
}
|
109
|
+
|
110
|
+
resp, data = Picasa::HTTP::Album.post_album(user_id, auth_token, params)
|
111
|
+
|
112
|
+
if resp.code != "201" or resp.message != "Created"
|
113
|
+
raise Exception, "Error creating album: #{resp.message}."
|
114
|
+
end
|
115
|
+
|
116
|
+
populate_attributes_from_xml data
|
117
|
+
self
|
118
|
+
end
|
119
|
+
|
120
|
+
# Post an album into Picasa.
|
121
|
+
# If cannot create the album returns false.
|
122
|
+
|
123
|
+
def picasa_save
|
124
|
+
raise_exception? do
|
125
|
+
picasa_save!
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Update the attributes of the current album.
|
130
|
+
# If cannot update, an exception is raised.
|
131
|
+
|
132
|
+
def picasa_update_attributes! params
|
133
|
+
resp, data = Picasa::HTTP::Album.update_album user_id, self.picasa_id, auth_token, params
|
134
|
+
|
135
|
+
if resp.code != "200" or resp.message != "OK"
|
136
|
+
raise Exception, "Error updating album."
|
137
|
+
end
|
138
|
+
|
139
|
+
populate_attributes_from_xml data
|
140
|
+
end
|
141
|
+
|
142
|
+
# Update the attributes of the current album.
|
143
|
+
# If cannot update, return false.
|
144
|
+
|
145
|
+
def picasa_update_attributes params
|
146
|
+
raise_exception? do
|
147
|
+
picasa_update_attributes! params
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# Update all attributes of the current album.
|
152
|
+
# If cannot update, an exception is raised.
|
153
|
+
|
154
|
+
def picasa_update!
|
155
|
+
params = {
|
156
|
+
:title => title,
|
157
|
+
:summary => summary,
|
158
|
+
:location => location,
|
159
|
+
:keywords => keywords
|
160
|
+
}
|
161
|
+
picasa_update_attributes! params
|
162
|
+
end
|
163
|
+
|
164
|
+
# Update all attributes of the current album.
|
165
|
+
# If cannot update, returns false.
|
166
|
+
|
167
|
+
def picasa_update
|
168
|
+
raise_exception? do
|
169
|
+
picasa_update!
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
|
174
|
+
# Destroy the current album.
|
175
|
+
# If cannot destroy it, an exception is raised.
|
176
|
+
|
177
|
+
def picasa_destroy!
|
178
|
+
resp, data = Picasa::HTTP::Album.delete_album user_id, self.picasa_id, auth_token
|
179
|
+
|
180
|
+
if resp.code != "200" or resp.message != "OK"
|
181
|
+
raise Exception, "Error destroying album."
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
# Destroy the current album and returns true.
|
186
|
+
# If cannot destroy it, returns false.
|
187
|
+
|
188
|
+
def picasa_destroy
|
189
|
+
raise_exception? do
|
190
|
+
picasa_destroy!
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def find_photo photo_id
|
195
|
+
photo_class.picasa_find user_id, picasa_id, photo_id, auth_token
|
196
|
+
end
|
197
|
+
|
198
|
+
# Find all photos from the current album. The operation is done only one time
|
199
|
+
# for an instance, if it it's needed to do it to refresh the data you can
|
200
|
+
# pass the parameter true so it can be reloaded.
|
201
|
+
|
202
|
+
def photos(reload = false)
|
203
|
+
@photos = photo_class.picasa_find_all user_id, picasa_id, auth_token if reload
|
204
|
+
@photos ||= photo_class.picasa_find_all user_id, picasa_id, auth_token
|
205
|
+
end
|
206
|
+
|
207
|
+
##############################################################################
|
208
|
+
# Private Methods #
|
209
|
+
##############################################################################
|
210
|
+
|
211
|
+
private
|
212
|
+
|
213
|
+
# Returns the user email based on the user_id methods
|
214
|
+
|
215
|
+
def user_email
|
216
|
+
"#{user_id}@gmail.com"
|
217
|
+
end
|
218
|
+
|
219
|
+
# Populates the attributes of the object based on the xml
|
220
|
+
|
221
|
+
def populate_attributes doc
|
222
|
+
hash = doc_to_hash doc
|
223
|
+
|
224
|
+
hash.keys.each do |k|
|
225
|
+
self.instance_variable_set("@#{k}", hash[k])
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def populate_attributes_from_xml xml
|
230
|
+
doc = Nokogiri::XML xml
|
231
|
+
entry = doc.css('entry')
|
232
|
+
populate_attributes entry
|
233
|
+
end
|
234
|
+
|
235
|
+
# Generate a hash representing the attributes of the album from a Nokogiri
|
236
|
+
# document
|
237
|
+
|
238
|
+
def doc_to_hash(doc)
|
239
|
+
hash = {
|
240
|
+
:picasa_id => doc.at_xpath('//gphoto:id').content,
|
241
|
+
:title => doc.at_css('title').content,
|
242
|
+
:summary => doc.at_css('summary').content,
|
243
|
+
:location => doc.at_xpath('gphoto:location').content,
|
244
|
+
:keywords => doc.at_xpath('//media:keywords').content,
|
245
|
+
:access => doc.at_xpath('gphoto:access').content,
|
246
|
+
:author_name => doc.at_css('author name').content,
|
247
|
+
:author_uri => doc.at_css('author uri').content,
|
248
|
+
:timestamp => Time.at(doc.at_xpath('gphoto:timestamp').content.slice(0..9).to_i),
|
249
|
+
:num_photos => doc.at_xpath('gphoto:numphotos').content.to_i,
|
250
|
+
:nickname => doc.at_xpath('gphoto:nickname').content,
|
251
|
+
:commenting_enable => doc.at_xpath('gphoto:commentingEnabled').content == "true" ? true : false,
|
252
|
+
:comment_count => doc.at_xpath('gphoto:commentCount').content.to_i,
|
253
|
+
:media_content_url => doc.at_xpath('//media:content').attr('url'),
|
254
|
+
:media_thumbnail_url => doc.at_xpath('//media:thumbnail').attr('url'),
|
255
|
+
:link_edit => doc.at_css('link[@rel="edit"]').attr('href')
|
256
|
+
}
|
257
|
+
end
|
258
|
+
|
259
|
+
def user_id
|
260
|
+
@user.picasa_id
|
261
|
+
end
|
262
|
+
|
263
|
+
def auth_token
|
264
|
+
@user.auth_token
|
265
|
+
end
|
266
|
+
|
267
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Module that offers methods to do the basic HTTP requests to authenticate
|
2
|
+
# an user with a google account.
|
3
|
+
|
4
|
+
module Picasa::Authentication
|
5
|
+
extend Picasa::Util
|
6
|
+
|
7
|
+
# Authenticate user and returns the authorization token
|
8
|
+
# if the operation succeeds other whise an exception is raised.
|
9
|
+
|
10
|
+
def self.authenticate user_id, password
|
11
|
+
resp, body = Picasa::HTTP::Authentication.authenticate user_id, password
|
12
|
+
|
13
|
+
if resp.code != '200' or resp.message != 'OK'
|
14
|
+
raise Exception, "Could not authenticate user. Code: #{resp.code}. Message: #{resp.message}"
|
15
|
+
end
|
16
|
+
|
17
|
+
extract_auth_token body
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# Module that offers methods to do the basic HTTP requests to services provided
|
2
|
+
# by Picasa to manipulate albums.
|
3
|
+
module Picasa
|
4
|
+
module HTTP
|
5
|
+
module Album
|
6
|
+
# Do a post request to create an album into the user account.
|
7
|
+
# The attributes used to create the album are:
|
8
|
+
#
|
9
|
+
# title, summary, location, keywords
|
10
|
+
|
11
|
+
def self.post_album user_id, auth_token, params
|
12
|
+
|
13
|
+
puts params.inspect
|
14
|
+
|
15
|
+
headers = albums_headers auth_token
|
16
|
+
|
17
|
+
uri = albums_uri user_id
|
18
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
19
|
+
|
20
|
+
# Render the album template
|
21
|
+
template_path = File.dirname(__FILE__) + '/../template/'
|
22
|
+
template = ERB.new File.open(template_path+"album.xml.erb").read
|
23
|
+
|
24
|
+
data = template.result(binding)
|
25
|
+
|
26
|
+
puts data
|
27
|
+
|
28
|
+
return http.post(uri.path, data, headers)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Do a put request to update album data
|
32
|
+
|
33
|
+
def self.update_album user_id, album_id, auth_token, params
|
34
|
+
resp, data = get_album user_id, album_id, auth_token
|
35
|
+
|
36
|
+
raise Exception, "Album not found." unless resp.code == "200"
|
37
|
+
|
38
|
+
data = update_album_xml data, params
|
39
|
+
|
40
|
+
headers = albums_headers auth_token, "If-Match" => "*"
|
41
|
+
|
42
|
+
uri = album_uri user_id, album_id
|
43
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
44
|
+
http.send_request('PUT',uri.path, data, headers)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Do a delete request to delete an album from a user
|
48
|
+
|
49
|
+
def self.delete_album user_id, album_id, auth_token
|
50
|
+
headers = albums_headers auth_token, "If-Match" => "*"
|
51
|
+
|
52
|
+
uri = album_uri user_id, album_id
|
53
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
54
|
+
http.send_request('DELETE',uri.path, nil, headers)
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
# Do a get request to retrieve all the albums from a user using the user_id.
|
59
|
+
|
60
|
+
def self.get_albums user_id, auth_token
|
61
|
+
headers = albums_headers auth_token
|
62
|
+
|
63
|
+
uri = albums_uri user_id
|
64
|
+
|
65
|
+
http = Net::HTTP.new(uri.host, 80)
|
66
|
+
http.get uri.path, headers
|
67
|
+
end
|
68
|
+
|
69
|
+
# Do a get request to retrieve one specific album from a user
|
70
|
+
|
71
|
+
def self.get_album user_id, album_id, auth_token = nil
|
72
|
+
headers = albums_headers auth_token
|
73
|
+
|
74
|
+
uri = album_uri user_id, album_id
|
75
|
+
|
76
|
+
http = Net::HTTP.new(uri.host, 80)
|
77
|
+
http.get uri.path, headers
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def self.update_album_xml xml, params
|
83
|
+
doc = Nokogiri::XML xml
|
84
|
+
doc.at_css('title').content = params[:title] if params[:title]
|
85
|
+
doc.at_css('summary').content = params[:summary] if params[:summary]
|
86
|
+
doc.at_xpath('//gphoto:access').content = params[:access] if params[:access]
|
87
|
+
doc.at_xpath('//gphoto:location').content = params[:location] if params[:location]
|
88
|
+
doc.at_xpath('//media:keywords').set_attribute("value", params[:keywords]) if params[:keywords]
|
89
|
+
doc.to_xml
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.albums_headers auth_token, opts = {}
|
93
|
+
headers = {}
|
94
|
+
headers["Content-Type"] = "application/atom+xml"
|
95
|
+
|
96
|
+
if auth_token and auth_token.length > 0
|
97
|
+
headers["Authorization"] = "GoogleLogin auth=#{auth_token}"
|
98
|
+
end
|
99
|
+
|
100
|
+
headers.merge opts
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.albums_uri user_id
|
104
|
+
URI.parse "http://picasaweb.google.com/data/feed/api/user/#{user_id}"
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.album_uri user_id, album_id
|
108
|
+
URI.parse "http://picasaweb.google.com/data/entry/api/user/#{user_id}/albumid/#{album_id}"
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# Module that offers methods to do the basic HTTP requests to authenticate user
|
2
|
+
# for Picasa.
|
3
|
+
|
4
|
+
module Picasa
|
5
|
+
module HTTP
|
6
|
+
module Authentication
|
7
|
+
|
8
|
+
HTTPS_PORT = 443
|
9
|
+
|
10
|
+
PICASA_SERVICE = 'lh2'
|
11
|
+
APP_NAME = 'BandManager'
|
12
|
+
|
13
|
+
# Do a post request to authenticate user with the e-mail and password provided
|
14
|
+
# and return the response and data of the request
|
15
|
+
|
16
|
+
def self.authenticate email, password
|
17
|
+
uri = uri_login
|
18
|
+
|
19
|
+
http = Net::HTTP.new(uri.host, HTTPS_PORT)
|
20
|
+
http.use_ssl=true
|
21
|
+
|
22
|
+
data = login_data email, password
|
23
|
+
|
24
|
+
headers = {'Content-Type' => 'application/x-www-form-urlencoded'}
|
25
|
+
resp, data = http.post(uri.path, data, headers)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def self.login_data email, password
|
31
|
+
"accountType=HOSTED_OR_GOOGLE&Email=#{email}&Passwd=#{password}&service=#{PICASA_SERVICE}&source=#{APP_NAME}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.uri_login
|
35
|
+
URI.parse "http://www.google.com/accounts/ClientLogin"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|