Merge lp:~mardy/shotwell/update-uoa into lp:~robert-ancell/shotwell/update-0.12.90

Proposed by Alberto Mardegan
Status: Merged
Merge reported by: Robert Ancell
Merged at revision: not available
Proposed branch: lp:~mardy/shotwell/update-uoa
Merge into: lp:~robert-ancell/shotwell/update-0.12.90
Diff against target: 1438 lines (+489/-601)
1 file modified
debian/patches/06_uoa.patch (+489/-601)
To merge this branch: bzr merge lp:~mardy/shotwell/update-uoa
Reviewer Review Type Date Requested Status
Robert Ancell Pending
Review via email: mp+121556@code.launchpad.net

Description of the change

Updated UOA patch.

To post a comment you must log in.
Revision history for this message
Sebastien Bacher (seb128) wrote :

Thanks mardy, I got that merged into the Ubuntu branch

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/patches/06_uoa.patch'
--- debian/patches/06_uoa.patch 2012-08-24 03:46:31 +0000
+++ debian/patches/06_uoa.patch 2012-08-28 08:16:23 +0000
@@ -1,8 +1,11 @@
1Description: use Ubuntu Online Accounts for Picasa, Facebook and Flickr export plugins
2Author: Alberto Mardegan <alberto.mardegan@canonical.com>
3
1=== modified file 'Makefile'4=== modified file 'Makefile'
2Index: shotwell-0.12.90/Makefile5Index: shotwell-0.12.90/Makefile
3===================================================================6===================================================================
4--- shotwell-0.12.90.orig/Makefile 2012-08-24 15:04:46.000000000 +12007--- shotwell-0.12.90.orig/Makefile 2012-08-28 10:25:15.248034132 +0300
5+++ shotwell-0.12.90/Makefile 2012-08-24 15:15:23.963988123 +12008+++ shotwell-0.12.90/Makefile 2012-08-28 10:25:15.288033628 +0300
6@@ -151,6 +151,7 @@9@@ -151,6 +151,7 @@
7 trash.ui 10 trash.ui
8 11
@@ -22,8 +25,8 @@
22 mkdir -p $(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps25 mkdir -p $(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps
23Index: shotwell-0.12.90/misc/org.yorba.shotwell.gschema.xml26Index: shotwell-0.12.90/misc/org.yorba.shotwell.gschema.xml
24===================================================================27===================================================================
25--- shotwell-0.12.90.orig/misc/org.yorba.shotwell.gschema.xml 2012-08-24 09:03:04.000000000 +120028--- shotwell-0.12.90.orig/misc/org.yorba.shotwell.gschema.xml 2012-08-24 00:03:04.000000000 +0300
26+++ shotwell-0.12.90/misc/org.yorba.shotwell.gschema.xml 2012-08-24 15:15:23.963988123 +120029+++ shotwell-0.12.90/misc/org.yorba.shotwell.gschema.xml 2012-08-28 10:25:15.288033628 +0300
27@@ -304,6 +304,12 @@30@@ -304,6 +304,12 @@
28 <description>Facebook user i.d. for the currently logged in user, if any</description>31 <description>Facebook user i.d. for the currently logged in user, if any</description>
29 </key>32 </key>
@@ -40,7 +43,7 @@
40Index: shotwell-0.12.90/misc/shotwell.application43Index: shotwell-0.12.90/misc/shotwell.application
41===================================================================44===================================================================
42--- /dev/null 1970-01-01 00:00:00.000000000 +000045--- /dev/null 1970-01-01 00:00:00.000000000 +0000
43+++ shotwell-0.12.90/misc/shotwell.application 2012-08-24 15:15:23.967988123 +120046+++ shotwell-0.12.90/misc/shotwell.application 2012-08-28 10:25:15.292033578 +0300
44@@ -0,0 +1,18 @@47@@ -0,0 +1,18 @@
45+<?xml version="1.0" encoding="UTF-8" ?>48+<?xml version="1.0" encoding="UTF-8" ?>
46+<application id="shotwell">49+<application id="shotwell">
@@ -62,8 +65,8 @@
62+</application>65+</application>
63Index: shotwell-0.12.90/plugins/Makefile66Index: shotwell-0.12.90/plugins/Makefile
64===================================================================67===================================================================
65--- shotwell-0.12.90.orig/plugins/Makefile 2012-08-24 09:03:04.000000000 +120068--- shotwell-0.12.90.orig/plugins/Makefile 2012-08-24 00:03:04.000000000 +0300
66+++ shotwell-0.12.90/plugins/Makefile 2012-08-24 15:15:23.967988123 +120069+++ shotwell-0.12.90/plugins/Makefile 2012-08-28 10:25:15.292033578 +0300
67@@ -4,7 +4,10 @@70@@ -4,7 +4,10 @@
68 DIST_FILES := \71 DIST_FILES := \
69 Makefile \72 Makefile \
@@ -78,8 +81,8 @@
78 all: $(ALL_PLUGINS)81 all: $(ALL_PLUGINS)
79Index: shotwell-0.12.90/plugins/Makefile.plugin.mk82Index: shotwell-0.12.90/plugins/Makefile.plugin.mk
80===================================================================83===================================================================
81--- shotwell-0.12.90.orig/plugins/Makefile.plugin.mk 2012-08-24 09:03:04.000000000 +120084--- shotwell-0.12.90.orig/plugins/Makefile.plugin.mk 2012-08-24 00:03:04.000000000 +0300
82+++ shotwell-0.12.90/plugins/Makefile.plugin.mk 2012-08-24 15:15:23.967988123 +120085+++ shotwell-0.12.90/plugins/Makefile.plugin.mk 2012-08-28 10:25:15.292033578 +0300
83@@ -27,6 +27,8 @@86@@ -27,6 +27,8 @@
84 # automatically include the shotwell-plugin-dev-1.0 package as a local dependency87 # automatically include the shotwell-plugin-dev-1.0 package as a local dependency
85 EXT_PKGS := $(PKGS)88 EXT_PKGS := $(PKGS)
@@ -91,8 +94,8 @@
91 SRC_FILES := ../common/Resources.vala $(SRC_FILES)94 SRC_FILES := ../common/Resources.vala $(SRC_FILES)
92Index: shotwell-0.12.90/plugins/common/RESTSupport.vala95Index: shotwell-0.12.90/plugins/common/RESTSupport.vala
93===================================================================96===================================================================
94--- shotwell-0.12.90.orig/plugins/common/RESTSupport.vala 2012-08-24 09:03:04.000000000 +120097--- shotwell-0.12.90.orig/plugins/common/RESTSupport.vala 2012-08-24 00:03:04.000000000 +0300
95+++ shotwell-0.12.90/plugins/common/RESTSupport.vala 2012-08-24 15:15:23.967988123 +120098+++ shotwell-0.12.90/plugins/common/RESTSupport.vala 2012-08-28 10:25:15.296033528 +0300
96@@ -314,7 +314,7 @@99@@ -314,7 +314,7 @@
97 old_url = message.get_uri().to_string(false);100 old_url = message.get_uri().to_string(false);
98 url_with_query = get_endpoint_url() + "?" + formdata_string;101 url_with_query = get_endpoint_url() + "?" + formdata_string;
@@ -105,7 +108,7 @@
105Index: shotwell-0.12.90/plugins/common/accounts.vala108Index: shotwell-0.12.90/plugins/common/accounts.vala
106===================================================================109===================================================================
107--- /dev/null 1970-01-01 00:00:00.000000000 +0000110--- /dev/null 1970-01-01 00:00:00.000000000 +0000
108+++ shotwell-0.12.90/plugins/common/accounts.vala 2012-08-24 15:15:23.967988123 +1200111+++ shotwell-0.12.90/plugins/common/accounts.vala 2012-08-28 10:25:15.296033528 +0300
109@@ -0,0 +1,54 @@112@@ -0,0 +1,54 @@
110+/* Copyright 2009-2011 Yorba Foundation113+/* Copyright 2009-2011 Yorba Foundation
111+ *114+ *
@@ -163,8 +166,8 @@
163+166+
164Index: shotwell-0.12.90/plugins/shotwell-publishing/FacebookPublishing.vala167Index: shotwell-0.12.90/plugins/shotwell-publishing/FacebookPublishing.vala
165===================================================================168===================================================================
166--- shotwell-0.12.90.orig/plugins/shotwell-publishing/FacebookPublishing.vala 2012-08-24 15:07:12.024005156 +1200169--- shotwell-0.12.90.orig/plugins/shotwell-publishing/FacebookPublishing.vala 2012-08-24 00:03:04.000000000 +0300
167+++ shotwell-0.12.90/plugins/shotwell-publishing/FacebookPublishing.vala 2012-08-24 15:15:23.967988123 +1200170+++ shotwell-0.12.90/plugins/shotwell-publishing/FacebookPublishing.vala 2012-08-28 11:11:00.554691926 +0300
168@@ -4,6 +4,8 @@171@@ -4,6 +4,8 @@
169 * (version 2.1 or later). See the COPYING file in this distribution.172 * (version 2.1 or later). See the COPYING file in this distribution.
170 */173 */
@@ -186,7 +189,7 @@
186 }189 }
187 190
188 namespace Publishing.Facebook {191 namespace Publishing.Facebook {
189@@ -163,14 +170,103 @@192@@ -163,11 +170,11 @@
190 private int publish_to_album = NO_ALBUM;193 private int publish_to_album = NO_ALBUM;
191 private weak Spit.Publishing.PluginHost host = null;194 private weak Spit.Publishing.PluginHost host = null;
192 private FacebookRESTSession session = null;195 private FacebookRESTSession session = null;
@@ -199,99 +202,7 @@
199 202
200 private Resolution target_resolution = Resolution.HIGH;203 private Resolution target_resolution = Resolution.HIGH;
201 204
202+ private struct LocaleLookup {205@@ -402,37 +409,56 @@
203+ public string prefix;
204+ public string translation;
205+ public string? exception_code;
206+ public string? exception_translation;
207+ public string? exception_code_2;
208+ public string? exception_translation_2;
209+ }
210+
211+ private const LocaleLookup[] locale_lookup_table = {
212+ { "es", "es-la", "ES", "es-es" },
213+ { "en", "en-gb", "US", "en-us" },
214+ { "fr", "fr-fr", "CA", "fr-ca" },
215+ { "pt", "pt-br", "PT", "pt-pt" },
216+ { "zh", "zh-cn", "HK", "zh-hk", "TW", "zh-tw" },
217+ { "af", "af-za" },
218+ { "ar", "ar-ar" },
219+ { "nb", "nb-no" },
220+ { "no", "nb-no" },
221+ { "id", "id-id" },
222+ { "ms", "ms-my" },
223+ { "ca", "ca-es" },
224+ { "cs", "cs-cz" },
225+ { "cy", "cy-gb" },
226+ { "da", "da-dk" },
227+ { "de", "de-de" },
228+ { "tl", "tl-ph" },
229+ { "ko", "ko-kr" },
230+ { "hr", "hr-hr" },
231+ { "it", "it-it" },
232+ { "lt", "lt-lt" },
233+ { "hu", "hu-hu" },
234+ { "nl", "nl-nl" },
235+ { "ja", "ja-jp" },
236+ { "nb", "nb-no" },
237+ { "no", "nb-no" },
238+ { "pl", "pl-pl" },
239+ { "ro", "ro-ro" },
240+ { "ru", "ru-ru" },
241+ { "sk", "sk-sk" },
242+ { "sl", "sl-sl" },
243+ { "sv", "sv-se" },
244+ { "th", "th-th" },
245+ { "vi", "vi-vn" },
246+ { "tr", "tr-tr" },
247+ { "el", "el-gr" },
248+ { "bg", "bg-bg" },
249+ { "sr", "sr-rs" },
250+ { "he", "he-il" },
251+ { "hi", "hi-in" },
252+ { "bn", "bn-in" },
253+ { "pa", "pa-in" },
254+ { "ta", "ta-in" },
255+ { "te", "te-in" },
256+ { "ml", "ml-in" }
257+ };
258+
259+ private string get_system_locale_as_facebook_locale() {
260+ unowned string? raw_system_locale = Intl.setlocale(LocaleCategory.ALL, "");
261+ if (raw_system_locale == null || raw_system_locale == "")
262+ return "www";
263+
264+ string system_locale = raw_system_locale.split(".")[0];
265+
266+ foreach (LocaleLookup locale_lookup in locale_lookup_table) {
267+ if (!system_locale.has_prefix(locale_lookup.prefix))
268+ continue;
269+
270+ if (locale_lookup.exception_code != null) {
271+ assert(locale_lookup.exception_translation != null);
272+
273+ if (system_locale.contains(locale_lookup.exception_code))
274+ return locale_lookup.exception_translation;
275+ }
276+
277+ if (locale_lookup.exception_code_2 != null) {
278+ assert(locale_lookup.exception_translation_2 != null);
279+
280+ if (system_locale.contains(locale_lookup.exception_code_2))
281+ return locale_lookup.exception_translation_2;
282+ }
283+
284+ return locale_lookup.translation;
285+ }
286+
287+ // default
288+ return "www";
289+ }
290+
291 public FacebookPublisher(Spit.Publishing.Service service,
292 Spit.Publishing.PluginHost host) {
293 debug("FacebookPublisher instantiated.");
294@@ -402,37 +498,80 @@
295 start();206 start();
296 }207 }
297 208
@@ -347,46 +258,22 @@
347+ data = account.get_session_parameters(out mechanism);258+ data = account.get_session_parameters(out mechanism);
348+ debug("Got account data");259+ debug("Got account data");
349+ } catch (GLib.Error e) {260+ } catch (GLib.Error e) {
350+ debug("EVENT: couldn't create session for account: %s",261+ warning("EVENT: couldn't create session for account: %s",
351+ e.message);262+ e.message);
352+ }
353+ }
354+
355+ if (auth_session == null) {
356+ debug("Creating unbound session");
357+ try {
358+ auth_session = new Signon.AuthSession(0, "oauth2");
359+ } catch (GLib.Error e) {
360+ debug("EVENT: AuthSession creation failed: %s", e.message);
361+ return;263+ return;
362+ }264+ }
363 }265 }
364+266+
365+ if (data == null) {267+ if (data == null) {
366+ debug("Using own params");268+ warning ("No account authentication data");
367+ data = new HashTable<string,Value?>(str_hash, str_equal);269+ host.post_error(new Spit.Publishing.PublishingError.SERVICE_ERROR(
368+ string facebook_locale = get_system_locale_as_facebook_locale();270+ "Error while accessing the account"));
369+ string host_name = "%s.facebook.com".printf(facebook_locale);271+ return;
370+ data.insert("Host", host_name);
371+ data.insert("AuthPath", "/dialog/oauth");
372+ data.insert("ClientId", APPLICATION_ID);
373+ data.insert("RedirectUri", "https://www.facebook.com/connect/login_success.html");
374+ string[] scopes = {
375+ "offline_access",
376+ "publish_stream",
377+ "user_photos",
378+ "user_videos"
379+ };
380+ data.insert("Scope", scopes);
381+ string[] response_type = {
382+ "token"
383+ };
384+ data.insert("ResponseType", response_type);
385+ }272+ }
386+273+
387+ var windowId = host.get_dialog_xid();274+ var windowId = host.get_dialog_xid();
388+ if (windowId != 0) {275+ if (windowId != 0) {
389+ data.insert("WindowId", windowId);276+ data.insert("WindowId", (uint)windowId);
390+ }277+ }
391+278+
392+ auth_session.process(data, mechanism, on_processed);279+ auth_session.process(data, mechanism, on_processed);
@@ -394,7 +281,7 @@
394 }281 }
395 282
396 private void do_save_session_information() {283 private void do_save_session_information() {
397@@ -562,30 +701,6 @@284@@ -562,30 +588,6 @@
398 host.post_error(err);285 host.post_error(err);
399 }286 }
400 287
@@ -425,7 +312,7 @@
425 private void on_session_authenticated() {312 private void on_session_authenticated() {
426 if (!is_running())313 if (!is_running())
427 return;314 return;
428@@ -773,14 +888,8 @@315@@ -773,14 +775,8 @@
429 get_persistent_uid(), get_persistent_user_name());316 get_persistent_uid(), get_persistent_user_name());
430 on_session_authenticated();317 on_session_authenticated();
431 } else {318 } else {
@@ -442,13 +329,12 @@
442 }329 }
443 }330 }
444 331
445@@ -909,39 +1018,14 @@332@@ -909,39 +905,14 @@
446 return (access_token != null && uid != null && user_name != null);333 return (access_token != null && uid != null && user_name != null);
447 }334 }
448 335
449- public void authenticate_with_parameters(string access_token, string uid, string user_name) {336- public void authenticate_with_parameters(string access_token, string uid, string user_name) {
450+ public void authenticate_with_parameters(string access_token, string? uid, string? user_name) {337- this.access_token = access_token;
451 this.access_token = access_token;
452- this.uid = uid;338- this.uid = uid;
453- this.user_name = user_name;339- this.user_name = user_name;
454- }340- }
@@ -477,7 +363,8 @@
477- access_token = access_token.replace("#access_token=", "");363- access_token = access_token.replace("#access_token=", "");
478- 364-
479- // we've got an access token!365- // we've got an access token!
480- this.access_token = access_token;366+ public void authenticate_with_parameters(string access_token, string? uid, string? user_name) {
367 this.access_token = access_token;
481- 368-
482- do_user_id_fetch_transaction();369- do_user_id_fetch_transaction();
483+ if (uid == null) {370+ if (uid == null) {
@@ -489,7 +376,7 @@
489 }376 }
490 377
491 public string get_endpoint_url() {378 public string get_endpoint_url() {
492@@ -1335,190 +1419,6 @@379@@ -1335,190 +1306,6 @@
493 }380 }
494 }381 }
495 382
@@ -682,8 +569,8 @@
682 private Gtk.Box pane_widget = null;569 private Gtk.Box pane_widget = null;
683Index: shotwell-0.12.90/plugins/shotwell-publishing/FlickrPublishing.vala570Index: shotwell-0.12.90/plugins/shotwell-publishing/FlickrPublishing.vala
684===================================================================571===================================================================
685--- shotwell-0.12.90.orig/plugins/shotwell-publishing/FlickrPublishing.vala 2012-08-24 15:12:30.611994126 +1200572--- shotwell-0.12.90.orig/plugins/shotwell-publishing/FlickrPublishing.vala 2012-08-24 00:03:04.000000000 +0300
686+++ shotwell-0.12.90/plugins/shotwell-publishing/FlickrPublishing.vala 2012-08-24 15:15:23.971988123 +1200573+++ shotwell-0.12.90/plugins/shotwell-publishing/FlickrPublishing.vala 2012-08-28 11:11:16.866844467 +0300
687@@ -4,6 +4,8 @@574@@ -4,6 +4,8 @@
688 * (version 2.1 or later). See the COPYING file in this distribution. 575 * (version 2.1 or later). See the COPYING file in this distribution.
689 */576 */
@@ -748,8 +635,8 @@
748+ data = account.get_session_parameters(out mechanism);635+ data = account.get_session_parameters(out mechanism);
749+ debug("Got account data");636+ debug("Got account data");
750+ } catch (GLib.Error e) {637+ } catch (GLib.Error e) {
751+ debug("EVENT: couldn't create session for account: %s",638+ warning("EVENT: couldn't create session for account: %s",
752+ e.message);639+ e.message);
753+ }640+ }
754+ }641+ }
755 642
@@ -774,7 +661,7 @@
774- session.set_request_phase_credentials(token, token_secret);661- session.set_request_phase_credentials(token, token_secret);
775+ var windowId = host.get_dialog_xid();662+ var windowId = host.get_dialog_xid();
776+ if (windowId != 0) {663+ if (windowId != 0) {
777+ data.insert("WindowId", windowId);664+ data.insert("WindowId", (uint)windowId);
778+ }665+ }
779 666
780- do_launch_system_browser(token);667- do_launch_system_browser(token);
@@ -1099,8 +986,8 @@
1099 return access_phase_token;986 return access_phase_token;
1100Index: shotwell-0.12.90/plugins/shotwell-publishing/Makefile987Index: shotwell-0.12.90/plugins/shotwell-publishing/Makefile
1101===================================================================988===================================================================
1102--- shotwell-0.12.90.orig/plugins/shotwell-publishing/Makefile 2012-08-24 15:13:53.000000000 +1200989--- shotwell-0.12.90.orig/plugins/shotwell-publishing/Makefile 2012-08-24 00:03:04.000000000 +0300
1103+++ shotwell-0.12.90/plugins/shotwell-publishing/Makefile 2012-08-24 15:15:23.971988123 +1200990+++ shotwell-0.12.90/plugins/shotwell-publishing/Makefile 2012-08-28 10:25:15.300033478 +0300
1104@@ -18,6 +18,7 @@991@@ -18,6 +18,7 @@
1105 FlickrPublishing.vala \992 FlickrPublishing.vala \
1106 YouTubePublishing.vala \993 YouTubePublishing.vala \
@@ -1111,8 +998,8 @@
1111 ../common/ui.vala998 ../common/ui.vala
1112Index: shotwell-0.12.90/plugins/shotwell-publishing/PicasaPublishing.vala999Index: shotwell-0.12.90/plugins/shotwell-publishing/PicasaPublishing.vala
1113===================================================================1000===================================================================
1114--- shotwell-0.12.90.orig/plugins/shotwell-publishing/PicasaPublishing.vala 2012-08-24 15:15:13.435988488 +12001001--- shotwell-0.12.90.orig/plugins/shotwell-publishing/PicasaPublishing.vala 2012-08-24 00:03:04.000000000 +0300
1115+++ shotwell-0.12.90/plugins/shotwell-publishing/PicasaPublishing.vala 2012-08-24 15:15:23.971988123 +12001002+++ shotwell-0.12.90/plugins/shotwell-publishing/PicasaPublishing.vala 2012-08-28 11:10:22.379612657 +0300
1116@@ -4,6 +4,8 @@1003@@ -4,6 +4,8 @@
1117 * (version 2.1 or later). See the COPYING file in this distribution. 1004 * (version 2.1 or later). See the COPYING file in this distribution.
1118 */1005 */
@@ -1142,173 +1029,170 @@
1142 1029
1143 public PicasaPublisher(Spit.Publishing.Service service,1030 public PicasaPublisher(Spit.Publishing.Service service,
1144 Spit.Publishing.PluginHost host) {1031 Spit.Publishing.PluginHost host) {
1145@@ -123,6 +131,29 @@1032@@ -83,18 +91,6 @@
1033 media_type |= p.get_media_type();
1034 }
1035
1036- private string get_user_authorization_url() {
1037- return "https://accounts.google.com/o/oauth2/auth?" +
1038- "response_type=code&" +
1039- "client_id=" + OAUTH_CLIENT_ID + "&" +
1040- "redirect_uri=" + Soup.URI.encode("urn:ietf:wg:oauth:2.0:oob", null) + "&" +
1041- "scope=" + Soup.URI.encode("http://picasaweb.google.com/data/", null) + "+" +
1042- Soup.URI.encode("https://www.googleapis.com/auth/userinfo.profile", null) + "&" +
1043- "state=connect&" +
1044- "access_type=offline&" +
1045- "approval_prompt=force";
1046- }
1047-
1048 private Album[] extract_albums(Xml.Node* document_root) throws Spit.Publishing.PublishingError {
1049 Album[] result = new Album[0];
1050
1051@@ -133,14 +129,6 @@
1146 return result;1052 return result;
1147 }1053 }
1148 1054
1149+ private string? extract_username(Xml.Node* document_root) throws Spit.Publishing.PublishingError {1055- internal string? get_persistent_refresh_token() {
1150+ Xml.Node* doc_node_iter = null;1056- return host.get_config_string("refresh_token", null);
1151+ if (document_root->name == "feed")1057- }
1152+ doc_node_iter = document_root->children;1058-
1153+ else1059- internal void set_persistent_refresh_token(string token) {
1154+ throw new Spit.Publishing.PublishingError.MALFORMED_RESPONSE("response root node " +1060- host.set_config_string("refresh_token", token);
1155+ "isn't a <feed>");1061- }
1156+1062-
1157+ for ( ; doc_node_iter != null; doc_node_iter = doc_node_iter->next) {1063 internal bool get_persistent_strip_metadata() {
1158+ if (doc_node_iter->name != "author")1064 return host.get_config_bool("strip_metadata", false);
1159+ continue;1065 }
1160+1066@@ -149,16 +137,6 @@
1161+ Xml.Node* author_node_iter = doc_node_iter->children;1067 host.set_config_bool("strip_metadata", strip_metadata);
1162+ for ( ; author_node_iter != null; author_node_iter = author_node_iter->next) {1068 }
1163+ if (author_node_iter->name == "name")1069
1164+ return author_node_iter->get_content();1070- internal void invalidate_persistent_session() {
1165+ }1071- debug("invalidating persisted Picasa Web Albums session.");
1166+1072-
1167+ }1073- host.unset_config_key("refresh_token");
1168+1074- }
1169+ return null;1075-
1170+ }1076- internal bool is_persistent_session_available() {
1171+1077- return get_persistent_refresh_token() != null;
1172 internal string? get_persistent_username() {1078- }
1173 return host.get_config_string("user_name", null);1079-
1174 }1080 public bool is_running() {
1175@@ -131,6 +162,10 @@1081 return running;
1176 return host.get_config_string("auth_token", null);1082 }
1177 }1083@@ -173,92 +151,69 @@
1178
1179+ internal string? get_persistent_auth_method() {
1180+ return host.get_config_string("auth_method", null);
1181+ }
1182+
1183 internal void set_persistent_username(string username) {
1184 host.set_config_string("user_name", username);
1185 }
1186@@ -139,11 +174,16 @@
1187 host.set_config_string("auth_token", auth_token);
1188 }
1189
1190+ internal void set_persistent_auth_method(string auth_method) {
1191+ host.set_config_string("auth_method", auth_method);
1192+ }
1193+
1194 internal void invalidate_persistent_session() {
1195 debug("invalidating persisted Picasa Web Albums session.");
1196
1197- host.unset_config_key("user_name");
1198- host.unset_config_key("auth_token");
1199+ set_persistent_username("");
1200+ set_persistent_auth_token("");
1201+ set_persistent_auth_method("");
1202 }
1203
1204 internal bool is_persistent_session_available() {
1205@@ -164,76 +204,89 @@
1206 1084
1207 debug("EVENT: user clicked 'Login' in welcome pane.");1085 debug("EVENT: user clicked 'Login' in welcome pane.");
1208 1086
1209- do_show_credentials_pane(CredentialsPane.Mode.INTRO);1087- do_launch_browser_for_authorization();
1210- }
1211-
1212- private void on_credentials_go_back() {
1213- if (!is_running())
1214- return;
1215-
1216- debug("EVENT: user clicked 'Go Back' in credentials pane.");
1217-
1218- do_show_service_welcome_pane();
1219- }
1220-
1221- private void on_credentials_login(string username, string password) {
1222- if (!is_running())
1223- return;
1224-
1225- debug("EVENT: user clicked 'Login' in credentials pane.");
1226-
1227- this.username = username;
1228-
1229- do_network_login(username, password);
1230- }
1231-
1232- private void on_token_fetch_complete(Publishing.RESTSupport.Transaction txn) {
1233- txn.completed.disconnect(on_token_fetch_complete);
1234- txn.network_error.disconnect(on_token_fetch_error);
1235-
1236- if (!is_running())
1237- return;
1238-
1239- if (session.is_authenticated()) // ignore these events if the session is already auth'd
1240- return;
1241-
1242- debug("EVENT: network transaction to fetch token for login completed successfully.");
1243-
1244- int index = txn.get_response().index_of("Auth=");
1245- string auth_substring = (index >= 0) ? txn.get_response()[index:txn.get_response().length] : "";
1246- auth_substring = auth_substring.chomp();
1247- string auth_token = auth_substring.substring(5);
1248+ do_hosted_web_authentication();1088+ do_hosted_web_authentication();
1249+ }1089 }
1250+1090
1091- private void on_auth_code_entry_pane_proceed(AuthCodeEntryPane sender, string code) {
1092- debug("EVENT: user clicked 'Continue' in authorization code entry pane.");
1093-
1094- sender.proceed.disconnect(on_auth_code_entry_pane_proceed);
1095-
1096- do_get_access_tokens(code);
1097- }
1098-
1099- private void on_browser_launched() {
1100- debug("EVENT: system web browser launched to solicit user authorization.");
1101-
1102- do_show_auth_code_entry_pane();
1103- }
1104-
1105- private void on_get_access_tokens_completed(Publishing.RESTSupport.Transaction txn) {
1106- txn.completed.disconnect(on_get_access_tokens_completed);
1107- txn.network_error.disconnect(on_get_access_tokens_error);
1251+ public void on_processed(Signon.AuthSession self, owned HashTable<string,Value?>? session_data, GLib.Error error){1108+ public void on_processed(Signon.AuthSession self, owned HashTable<string,Value?>? session_data, GLib.Error error){
1252+ if (error != null) {1109+ if (error != null) {
1253+ debug("got error: %s", error.message);1110+ debug("got error: %s", error.message);
1254+ /* TODO: handle errors */1111+ /* TODO: handle errors */
1255+ return;1112+ return;
1256+ }1113+ }
1257+1114
1115- debug("EVENT: network transaction to exchange authorization code for access tokens " +
1116- "completed successfully.");
1258+ host.set_service_locked(true);1117+ host.set_service_locked(true);
1259+ host.install_account_fetch_wait_pane();1118+ host.install_account_fetch_wait_pane();
1260 1119
1261 session.authenticated.connect(on_session_authenticated);1120- do_extract_tokens(txn.get_response());
1262- session.authenticate(auth_token, username);1121- }
1263+1122-
1123- private void on_get_access_tokens_error(Publishing.RESTSupport.Transaction txn,
1124- Spit.Publishing.PublishingError err) {
1125- txn.completed.disconnect(on_get_access_tokens_completed);
1126- txn.network_error.disconnect(on_get_access_tokens_error);
1127+ session.authenticated.connect(on_session_authenticated);
1128
1129- debug("EVENT: network transaction to exchange authorization code for access tokens " +
1130- "failed; response = '%s'", txn.get_response());
1131- }
1132-
1133- private void on_refresh_token_available(string token) {
1134- debug("EVENT: an OAuth refresh token has become available.");
1135-
1136- do_save_refresh_token_to_configuration_system(token);
1137- }
1138-
1139- private void on_access_token_available(string token) {
1140- debug("EVENT: an OAuth access token has become available.");
1141-
1142- do_authenticate_session(token);
1143- }
1144-
1145- private void on_not_set_up_pane_proceed(NotSetUpMessagePane sender) {
1146- debug("EVENT: user clicked 'Continue' in Account Not Set Up Message Pane.");
1147-
1148- sender.proceed.disconnect(on_not_set_up_pane_proceed);
1149-
1150- do_launch_browser_for_authorization();
1264+ if (session_data.lookup("AccessToken") != null) {1151+ if (session_data.lookup("AccessToken") != null) {
1265+ string token = session_data.lookup("AccessToken").get_string();1152+ string token = session_data.lookup("AccessToken").get_string();
1266+ debug("OAuth Access Token: %s", token);1153+ debug("OAuth Access Token: %s", token);
1267+ session.authenticate(token, null, "OAuth2");1154+ session.authenticate(token, "OAuth2");
1268+ } else if (session_data.lookup("AuthToken") != null) {1155+ } else if (session_data.lookup("AuthToken") != null) {
1269+ string token = session_data.lookup("AuthToken").get_string();1156+ string token = session_data.lookup("AuthToken").get_string();
1270+ debug("ClientLogin Access Token: %s", token);1157+ debug("ClientLogin Access Token: %s", token);
1271+ session.authenticate(token, null, "ClientLogin");1158+ session.authenticate(token, "ClientLogin");
1272+ } else {1159+ } else {
1273+ debug("Access token not present!");1160+ debug("Access token not present!");
1274+ }1161+ }
1275 }1162 }
1163-
1164- private void on_refresh_access_token_transaction_completed(Publishing.RESTSupport.Transaction
1165- txn) {
1166- txn.completed.disconnect(on_refresh_access_token_transaction_completed);
1167- txn.network_error.disconnect(on_refresh_access_token_transaction_error);
1168-
1169- if (!is_running())
1170- return;
1276 1171
1277- private void on_token_fetch_error(Publishing.RESTSupport.Transaction bad_txn,
1278- Spit.Publishing.PublishingError err) {
1279- bad_txn.completed.disconnect(on_token_fetch_complete);
1280- bad_txn.network_error.disconnect(on_token_fetch_error);
1281-
1282- if (!is_running())
1283- return;
1284-
1285- if (session.is_authenticated()) // ignore these events if the session is already auth'd1172- if (session.is_authenticated()) // ignore these events if the session is already auth'd
1286- return;1173- return;
1287-
1288- debug("EVENT: network transaction to fetch token for login failed; response = '%s'.",
1289- bad_txn.get_response());
1290-
1291- // HTTP error 403 is invalid authentication -- if we get this error during token fetch
1292- // then we can just show the login screen again with a retry message; if we get any error
1293- // other than 403 though, we can't recover from it, so just post the error to the user
1294- if (bad_txn.get_status_code() == 403) {
1295- if (bad_txn.get_response().contains("CaptchaRequired"))
1296- do_show_credentials_pane(CredentialsPane.Mode.ADDITIONAL_SECURITY);
1297- else
1298- do_show_credentials_pane(CredentialsPane.Mode.FAILED_RETRY);
1299- }
1300- else {
1301- host.post_error(err);
1302- }
1303+ private void do_hosted_web_authentication() {1174+ private void do_hosted_web_authentication() {
1304+ debug("ACTION: doing hosted web authentication.");1175+ debug("ACTION: doing hosted web authentication.");
1305+1176
1177- debug("EVENT: refresh access token transaction completed successfully.");
1178-
1179- do_extract_tokens(txn.get_response());
1180- }
1181-
1182- private void on_refresh_access_token_transaction_error(Publishing.RESTSupport.Transaction txn,
1183- Spit.Publishing.PublishingError err) {
1184- txn.completed.disconnect(on_refresh_access_token_transaction_completed);
1185- txn.network_error.disconnect(on_refresh_access_token_transaction_error);
1186-
1187- if (!is_running())
1188- return;
1306+ HashTable<string,Value?> data = null;1189+ HashTable<string,Value?> data = null;
1307+ string mechanism = "user_agent";1190+ string mechanism = "user_agent";
1308+1191+
1309+ SharingAccounts accounts =1192+ SharingAccounts accounts =
1310+ new SharingAccounts();1193+ new SharingAccounts();
1311+1194
1195- if (session.is_authenticated()) // ignore these events if the session is already auth'd
1312+ SharingAccount? account = accounts.get_account_for_provider("google");1196+ SharingAccount? account = accounts.get_account_for_provider("google");
1313+ if (account != null) {1197+ if (account != null) {
1314+ try {1198+ try {
@@ -1316,41 +1200,24 @@
1316+ data = account.get_session_parameters(out mechanism);1200+ data = account.get_session_parameters(out mechanism);
1317+ debug("Got account data");1201+ debug("Got account data");
1318+ } catch (GLib.Error e) {1202+ } catch (GLib.Error e) {
1319+ debug("EVENT: couldn't create session for account: %s",1203+ warning("EVENT: couldn't create session for account: %s",
1320+ e.message);1204+ e.message);
1321+ }
1322+ }
1323+
1324+ if (auth_session == null) {
1325+ debug("Creating unbound session");
1326+ try {
1327+ auth_session = new Signon.AuthSession(0, "oauth2");
1328+ } catch (GLib.Error e) {
1329+ debug("EVENT: AuthSession creation failed: %s", e.message);
1330+ return;
1331+ }1205+ }
1332+ }1206+ }
1333+1207+
1334+ if (data == null) {1208+ if (data == null) {
1335+ debug("Using own params");1209+ warning ("No account authentication data");
1336+ data = new HashTable<string,Value?>(str_hash, str_equal);1210+ host.post_error(new Spit.Publishing.PublishingError.SERVICE_ERROR(
1337+ data.insert("Host", "accounts.google.com");1211+ "Error while accessing the account"));
1338+ data.insert("AuthPath", "o/oauth2/auth");1212 return;
1339+ data.insert("ClientId", "1041829795610-htf69c529db58qcq8jvf58bijn1ie3oi.apps.googleusercontent.com");
1340+ data.insert("RedirectUri", "http://www.mardy.it/oauth2callback");
1341+ string[] scopes = {
1342+ "https://picasaweb.google.com/data/"
1343+ };
1344+ data.insert("Scope", scopes);
1345+ string[] response_type = {
1346+ "token"
1347+ };
1348+ data.insert("ResponseType", response_type);
1349+ }1213+ }
1350+1214
1215- debug("EVENT: refresh access token transaction caused a network error.");
1216-
1217- host.post_error(err);
1351+ var windowId = host.get_dialog_xid();1218+ var windowId = host.get_dialog_xid();
1352+ if (windowId != 0) {1219+ if (windowId != 0) {
1353+ data.insert("WindowId", windowId);1220+ data.insert("WindowId", (uint)windowId);
1354+ }1221+ }
1355+1222+
1356+ auth_session.process(data, mechanism, on_processed);1223+ auth_session.process(data, mechanism, on_processed);
@@ -1358,7 +1225,7 @@
1358 }1225 }
1359 1226
1360 private void on_session_authenticated() {1227 private void on_session_authenticated() {
1361@@ -271,25 +324,7 @@1228@@ -313,19 +268,7 @@
1362 debug("EVENT: fetching account and album information failed; response = '%s'.",1229 debug("EVENT: fetching account and album information failed; response = '%s'.",
1363 bad_txn.get_response());1230 bad_txn.get_response());
1364 1231
@@ -1366,161 +1233,286 @@
1366- // if we get a 404 error (resource not found) on the initial album fetch, then the1233- // if we get a 404 error (resource not found) on the initial album fetch, then the
1367- // user's album feed doesn't exist -- this occurs when the user has a valid Google1234- // user's album feed doesn't exist -- this occurs when the user has a valid Google
1368- // account but it hasn't yet been set up for use with Picasa. In this case, we1235- // account but it hasn't yet been set up for use with Picasa. In this case, we
1369- // re-display the credentials capture pane with an "account not set up" message.1236- // display an informational pane with an "account not set up" message. In addition, we
1370- // In addition, we deauthenticate the session. Deauth is neccessary because we1237- // deauthenticate the session. Deauth is neccessary because must've previously auth'd
1371- // did previously auth the user's account. If we get any other kind of error, we can't1238- // the user's account to even be able to query the album feed.
1372- // recover, so just post it to the user1239- session.deauthenticate();
1373- session.deauthenticate();1240- do_show_not_set_up_pane();
1374- do_show_credentials_pane(CredentialsPane.Mode.NOT_SET_UP);
1375- } else if (bad_txn.get_status_code() == 403) {
1376- // if we get a 403 error (authentication failed) then we need to return to the login
1377- // screen because the user's auth token is no longer valid and he or she needs to
1378- // login again to obtain a new one
1379- session.deauthenticate();
1380- do_show_credentials_pane(CredentialsPane.Mode.INTRO);
1381- } else {1241- } else {
1242- // If we get any other kind of error, we can't recover, so just post it to the user
1382- host.post_error(err);1243- host.post_error(err);
1383- }1244- }
1384+ host.post_error(err);1245+ host.post_error(err);
1385 }1246 }
1386 1247
1387 private void on_publishing_options_logout() {1248 private void on_publishing_options_logout() {
1388@@ -414,34 +449,6 @@1249@@ -335,7 +278,6 @@
1250 debug("EVENT: user clicked 'Logout' in the publishing options pane.");
1251
1252 session.deauthenticate();
1253- invalidate_persistent_session();
1254
1255 do_show_service_welcome_pane();
1256 }
1257@@ -453,94 +395,6 @@
1389 host.install_welcome_pane(SERVICE_WELCOME_MESSAGE, on_service_welcome_login);1258 host.install_welcome_pane(SERVICE_WELCOME_MESSAGE, on_service_welcome_login);
1390 }1259 }
1391 1260
1392- private void do_show_credentials_pane(CredentialsPane.Mode mode) {1261- private void do_launch_browser_for_authorization() {
1393- debug("ACTION: showing credentials capture pane in %s mode.", mode.to_string());1262- string auth_url = get_user_authorization_url();
1394- 1263-
1395- CredentialsPane creds_pane = new CredentialsPane(host, mode);1264- debug("ACTION: launching external web browser to get user authorization; " +
1396- creds_pane.go_back.connect(on_credentials_go_back);1265- "authorization URL = '%s'", auth_url);
1397- creds_pane.login.connect(on_credentials_login);1266-
1398-1267- try {
1399- host.install_dialog_pane(creds_pane);1268- Process.spawn_command_line_async("xdg-open " + auth_url);
1400- }1269- } catch (SpawnError e) {
1401-1270- host.post_error(new Spit.Publishing.PublishingError.LOCAL_FILE_ERROR(
1402- private void do_network_login(string username, string password) {1271- _("couldn't launch system web browser to complete Picasa Web Albums login")));
1403- debug("ACTION: running network login transaction for user = '%s'.", username);1272- return;
1273- }
1274-
1275- on_browser_launched();
1276- }
1277-
1278- private void do_show_auth_code_entry_pane() {
1279- debug("ACTION: showing OAuth authorization code entry pane.");
1280-
1281- Gtk.Builder builder = new Gtk.Builder();
1282-
1283- try {
1284- builder.add_from_file(host.get_module_file().get_parent().get_child(
1285- "picasa_auth_code_entry_pane.glade").get_path());
1286- } catch (Error e) {
1287- warning("Could not parse UI file! Error: %s.", e.message);
1288- host.post_error(
1289- new Spit.Publishing.PublishingError.LOCAL_FILE_ERROR(
1290- _("A file required for publishing is unavailable. Publishing to Picasa Web Albums can't continue.")));
1291- return;
1292- }
1293-
1294- AuthCodeEntryPane pane = new AuthCodeEntryPane(builder);
1295- pane.proceed.connect(on_auth_code_entry_pane_proceed);
1296- host.install_dialog_pane(pane);
1297- }
1298-
1299- private void do_get_access_tokens(string code) {
1300- debug("ACTION: exchanging OAuth authorization code '%s' for access token.", code);
1301-
1302- GetAccessTokensTransaction txn = new GetAccessTokensTransaction(session, code);
1303- txn.completed.connect(on_get_access_tokens_completed);
1304- txn.network_error.connect(on_get_access_tokens_error);
1305-
1306- try {
1307- txn.execute();
1308- } catch (Spit.Publishing.PublishingError err) {
1309- host.post_error(err);
1310- }
1311- }
1312-
1313- private void do_extract_tokens(string response_body) {
1314- debug("ACTION: extracting OAuth tokens from body of server response");
1315-
1316- Json.Parser parser = new Json.Parser();
1317-
1318- try {
1319- parser.load_from_data(response_body);
1320- } catch (Error err) {
1321- host.post_error(new Spit.Publishing.PublishingError.MALFORMED_RESPONSE(
1322- "Couldn't parse JSON response: " + err.message));
1323- return;
1324- }
1325-
1326- Json.Object response_obj = parser.get_root().get_object();
1327-
1328- if ((!response_obj.has_member("access_token")) && (!response_obj.has_member("refresh_token"))) {
1329- host.post_error(new Spit.Publishing.PublishingError.MALFORMED_RESPONSE(
1330- "neither access_token nor refresh_token not present in server response"));
1331- return;
1332- }
1333-
1334- if (response_obj.has_member("refresh_token")) {
1335- string refresh_token = response_obj.get_string_member("refresh_token");
1336-
1337- if (refresh_token != "")
1338- on_refresh_token_available(refresh_token);
1339- }
1340-
1341- if (response_obj.has_member("access_token")) {
1342- string access_token = response_obj.get_string_member("access_token");
1343-
1344- if (access_token != "")
1345- on_access_token_available(access_token);
1346- }
1347- }
1348-
1349 private void do_extract_username(string response_body) {
1350 debug("ACTION: extracting username from body of server response");
1351
1352@@ -562,66 +416,8 @@
1353 if (username != "")
1354 this.username = username;
1355 }
1356-
1357- if (response_obj.has_member("access_token")) {
1358- string access_token = response_obj.get_string_member("access_token");
1359-
1360- if (access_token != "")
1361- on_access_token_available(access_token);
1362- }
1363 }
1364
1365- private void do_save_refresh_token_to_configuration_system(string token) {
1366- debug("ACTION: saving OAuth refresh token to configuration system");
1367-
1368- set_persistent_refresh_token(token);
1369- }
1370-
1371- private void do_refresh_session(string refresh_token) {
1372- debug("ACTION: using OAuth refresh token to refresh session.");
1404- 1373-
1405- host.install_login_wait_pane();1374- host.install_login_wait_pane();
1406-1375-
1407- TokenFetchTransaction fetch_trans = new TokenFetchTransaction(session, username, password);1376- RefreshAccessTokenTransaction txn = new RefreshAccessTokenTransaction(session, refresh_token);
1408- fetch_trans.network_error.connect(on_token_fetch_error);1377-
1409- fetch_trans.completed.connect(on_token_fetch_complete);1378- txn.completed.connect(on_refresh_access_token_transaction_completed);
1410-1379- txn.network_error.connect(on_refresh_access_token_transaction_error);
1380-
1411- try {1381- try {
1412- fetch_trans.execute();1382- txn.execute();
1413- } catch (Spit.Publishing.PublishingError err) {1383- } catch (Spit.Publishing.PublishingError err) {
1414- // 403 errors are recoverable, so don't post the error to our host immediately;1384- host.post_error(err);
1415- // instead, try to recover from it1385- }
1416- on_token_fetch_error(fetch_trans, err);1386- }
1417- }1387-
1418- }1388- private void do_authenticate_session(string token) {
1419- 1389- debug("ACTION: authenticating session.");
1420 private void do_save_auth_info() {1390-
1421 debug("ACTION: saving authentication information to configuration system.");1391- session.authenticated.connect(on_session_authenticated);
1422 1392- session.authenticate(token);
1423@@ -449,6 +456,7 @@1393- }
1424 1394-
1425 set_persistent_auth_token(session.get_auth_token());1395- private void do_show_not_set_up_pane() {
1426 set_persistent_username(session.get_username());1396- debug("ACTION: showing account not set up message pane");
1427+ set_persistent_auth_method(session.get_auth_method());1397-
1398- Gtk.Builder builder = new Gtk.Builder();
1399-
1400- try {
1401- builder.add_from_file(host.get_module_file().get_parent().get_child(
1402- "picasa_not_set_up_pane.glade").get_path());
1403- } catch (Error e) {
1404- warning("Could not parse UI file! Error: %s.", e.message);
1405- host.post_error(
1406- new Spit.Publishing.PublishingError.LOCAL_FILE_ERROR(
1407- _("A file required for publishing is unavailable. Publishing to Picasa Web Albums can't continue.")));
1408- return;
1409- }
1410-
1411- NotSetUpMessagePane pane = new NotSetUpMessagePane(builder);
1412- pane.proceed.connect(on_not_set_up_pane_proceed);
1413- host.install_dialog_pane(pane);
1414- }
1415-
1416 private void do_fetch_username() {
1417 debug("ACTION: running network transaction to fetch username.");
1418
1419@@ -771,11 +567,7 @@
1420
1421 running = true;
1422
1423- if (is_persistent_session_available()) {
1424- do_refresh_session(get_persistent_refresh_token());
1425- } else {
1426- do_show_service_welcome_pane();
1427- }
1428+ do_show_service_welcome_pane();
1428 }1429 }
1429 1430
1430 private void do_fetch_account_information() {1431 public void stop() {
1431@@ -485,6 +493,8 @@1432@@ -801,6 +593,7 @@
1432 1433
1433 try {
1434 albums = extract_albums(response_doc.get_root_node());
1435+ username = extract_username(response_doc.get_root_node());
1436+ set_persistent_username(username);
1437 } catch (Spit.Publishing.PublishingError err) {
1438 host.post_error(err);
1439 return;
1440@@ -567,7 +577,8 @@
1441
1442 if (is_persistent_session_available()) {
1443 username = get_persistent_username();
1444- session.authenticate(get_persistent_auth_token(), get_persistent_username());
1445+ session.authenticate(get_persistent_auth_token(), get_persistent_username(),
1446+ get_persistent_auth_method());
1447 do_fetch_account_information();
1448 } else {
1449 do_show_service_welcome_pane();
1450@@ -598,6 +609,7 @@
1451 internal class Session : Publishing.RESTSupport.Session {1434 internal class Session : Publishing.RESTSupport.Session {
1452 private string? auth_token = null;1435 private string? auth_token = null;
1453 private string? username = null;
1454+ private string? auth_method = null;1436+ private string? auth_method = null;
1455 1437
1456 public Session() {1438 public Session() {
1457 }1439 }
1458@@ -606,9 +618,10 @@1440@@ -809,45 +602,24 @@
1459 return (auth_token != null);1441 return (auth_token != null);
1460 }1442 }
1461 1443
1462- public void authenticate(string auth_token, string username) {1444- public void authenticate(string auth_token) {
1463+ public void authenticate(string auth_token, string? username, string auth_method) {1445+ public void authenticate(string auth_token, string auth_method) {
1464 this.auth_token = auth_token;1446 this.auth_token = auth_token;
1465 this.username = username;
1466+ this.auth_method = auth_method;1447+ this.auth_method = auth_method;
1467 1448
1468 notify_authenticated();1449 notify_authenticated();
1469 }1450 }
1470@@ -616,6 +629,7 @@1451
1471 public void deauthenticate() {1452 public void deauthenticate() {
1472 auth_token = null;1453 auth_token = null;
1473 username = null;
1474+ auth_method = null;1454+ auth_method = null;
1475 }1455 }
1476 1456
1477 public string? get_username() {
1478@@ -625,19 +639,9 @@
1479 public string? get_auth_token() {1457 public string? get_auth_token() {
1480 return auth_token;1458 return auth_token;
1481 }1459 }
1482-}1460-}
1483-1461
1484-internal class TokenFetchTransaction : Publishing.RESTSupport.Transaction {1462-internal class GetAccessTokensTransaction : Publishing.RESTSupport.Transaction {
1485- private const string ENDPOINT_URL = "https://www.google.com/accounts/ClientLogin";1463- private const string ENDPOINT_URL = "https://accounts.google.com/o/oauth2/token";
1486-1464-
1487- public TokenFetchTransaction(Session session, string username, string password) {1465- public GetAccessTokensTransaction(Session session, string auth_code) {
1488- base.with_endpoint_url(session, ENDPOINT_URL);1466- base.with_endpoint_url(session, ENDPOINT_URL);
1489-1467-
1490- add_argument("accountType", "HOSTED_OR_GOOGLE");1468- add_argument("code", auth_code);
1491- add_argument("Email", username);1469- add_argument("client_id", OAUTH_CLIENT_ID);
1492- add_argument("Passwd", password);1470- add_argument("client_secret", OAUTH_CLIENT_SECRET);
1493- add_argument("service", "lh2");1471- add_argument("redirect_uri", "urn:ietf:wg:oauth:2.0:oob");
1494- add_argument("source", "yorba-shotwell-" + _VERSION);1472- add_argument("grant_type", "authorization_code");
1495+1473- }
1474-}
1475-
1476-internal class RefreshAccessTokenTransaction : Publishing.RESTSupport.Transaction {
1477- private const string ENDPOINT_URL = "https://accounts.google.com/o/oauth2/token";
1478-
1479- public RefreshAccessTokenTransaction(Session session, string refresh_token) {
1480- base.with_endpoint_url(session, ENDPOINT_URL);
1481-
1482- add_argument("client_id", OAUTH_CLIENT_ID);
1483- add_argument("client_secret", OAUTH_CLIENT_SECRET);
1484- add_argument("refresh_token", refresh_token);
1485- add_argument("grant_type", "refresh_token");
1496+ public string? get_auth_method() {1486+ public string? get_auth_method() {
1497+ return auth_method;1487+ return auth_method;
1498 }1488 }
1499 }1489 }
1500 1490
1501@@ -652,12 +656,19 @@1491@@ -862,7 +634,13 @@
1502 base.with_endpoint_url(session, endpoint_url, method);1492 base.with_endpoint_url(session, endpoint_url, method);
1503 assert(session.is_authenticated());1493 assert(session.is_authenticated());
1504 1494
1505- add_header("Authorization", "GoogleLogin auth=%s".printf(session.get_auth_token()));1495- add_header("Authorization", "Bearer " + session.get_auth_token());
1506+ if (session.get_auth_method() == "ClientLogin") {1496+ if (session.get_auth_method() == "ClientLogin") {
1507+ add_header("Authorization",1497+ add_header("Authorization",
1508+ "GoogleLogin auth=%s".printf(session.get_auth_token()));1498+ "GoogleLogin auth=" + session.get_auth_token());
1509+ } else {1499+ } else {
1510+ add_argument("access_token", session.get_auth_token());
1511+ add_header("Authorization",1500+ add_header("Authorization",
1512+ "Bearer %s".printf(session.get_auth_token()));1501+ "Bearer " + session.get_auth_token());
1513+ }1502+ }
1514 }1503 }
1515 }1504 }
1516 1505
1506@@ -875,7 +653,7 @@
1507 }
1508
1517 internal class AlbumDirectoryTransaction : AuthenticatedTransaction {1509 internal class AlbumDirectoryTransaction : AuthenticatedTransaction {
1518- private const string ENDPOINT_URL = "http://picasaweb.google.com/data/feed/api/user/" +1510- private const string ENDPOINT_URL = "http://picasaweb.google.com/data/feed/api/user/" +
1519+ private const string ENDPOINT_URL = "https://picasaweb.google.com/data/feed/api/user/" +1511+ private const string ENDPOINT_URL = "https://picasaweb.google.com/data/feed/api/user/" +
1520 "default";1512 "default";
1521 1513
1522 public AlbumDirectoryTransaction(Session session) {1514 public AlbumDirectoryTransaction(Session session) {
1523@@ -674,7 +685,7 @@1515@@ -892,7 +670,7 @@
1524 }1516 }
1525 1517
1526 private class AlbumCreationTransaction : AuthenticatedTransaction {1518 private class AlbumCreationTransaction : AuthenticatedTransaction {
@@ -1529,227 +1521,123 @@
1529 "default";1521 "default";
1530 private const string ALBUM_ENTRY_TEMPLATE = "<?xml version='1.0' encoding='utf-8'?><entry xmlns='http://www.w3.org/2005/Atom' xmlns:gphoto='http://schemas.google.com/photos/2007'><title type='text'>%s</title><gphoto:access>%s</gphoto:access><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#album'></category></entry>";1522 private const string ALBUM_ENTRY_TEMPLATE = "<?xml version='1.0' encoding='utf-8'?><entry xmlns='http://www.w3.org/2005/Atom' xmlns:gphoto='http://schemas.google.com/photos/2007'><title type='text'>%s</title><gphoto:access>%s</gphoto:access><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#album'></category></entry>";
1531 1523
1532@@ -747,8 +758,14 @@1524@@ -971,9 +749,14 @@
1533 // that we've been building up1525 // that we've been building up
1534 Soup.Message outbound_message =1526 Soup.Message outbound_message =
1535 soup_form_request_new_from_multipart(get_endpoint_url(), message_parts);1527 soup_form_request_new_from_multipart(get_endpoint_url(), message_parts);
1536- outbound_message.request_headers.append("Authorization", "GoogleLogin auth=%s".printf(session.get_auth_token()));1528- outbound_message.request_headers.append("Authorization", "Bearer " +
1529- session.get_auth_token());
1537 set_message(outbound_message);1530 set_message(outbound_message);
1538+ if (session.get_auth_method() == "ClientLogin") {1531+ if (session.get_auth_method() == "ClientLogin") {
1539+ add_header("Authorization",1532+ add_header("Authorization",
1540+ "GoogleLogin auth=%s".printf(session.get_auth_token()));1533+ "GoogleLogin auth=" + session.get_auth_token());
1541+ } else {1534+ } else {
1542+ add_header("Authorization",1535+ add_header("Authorization",
1543+ "Bearer %s".printf(session.get_auth_token()));1536+ "Bearer " + session.get_auth_token());
1544+ }1537+ }
1545 1538
1546 // send the message and get its response1539 // send the message and get its response
1547 set_is_executed(true);1540 set_is_executed(true);
1548@@ -756,199 +773,6 @@1541@@ -981,95 +764,6 @@
1549 }1542 }
1550 }1543 }
1551 1544
1552-internal class CredentialsPane : Spit.Publishing.DialogPane, GLib.Object {1545-internal class AuthCodeEntryPane : Spit.Publishing.DialogPane, GLib.Object {
1553- public enum Mode {1546- private Gtk.Box pane_widget = null;
1554- INTRO,1547- private Gtk.Button continue_button = null;
1555- FAILED_RETRY,1548- private Gtk.Entry entry = null;
1556- NOT_SET_UP,1549- private Gtk.Label entry_caption = null;
1557- ADDITIONAL_SECURITY;1550- private Gtk.Label explanatory_text = null;
1558-1551-
1559- public string to_string() {1552- public signal void proceed(AuthCodeEntryPane sender, string authorization_code);
1560- switch (this) {1553-
1561- case Mode.INTRO:1554- public AuthCodeEntryPane(Gtk.Builder builder) {
1562- return "INTRO";1555- assert(builder != null);
1563-1556- assert(builder.get_objects().length() > 0);
1564- case Mode.FAILED_RETRY:1557-
1565- return "FAILED_RETRY";1558- explanatory_text = builder.get_object("explanatory_text") as Gtk.Label;
1566-1559- entry_caption = builder.get_object("entry_caption") as Gtk.Label;
1567- case Mode.NOT_SET_UP:1560- entry = builder.get_object("entry") as Gtk.Entry;
1568- return "NOT_SET_UP";1561- continue_button = builder.get_object("continue_button") as Gtk.Button;
1569-1562-
1570- case Mode.ADDITIONAL_SECURITY:1563- pane_widget = builder.get_object("pane_widget") as Gtk.Box;
1571- return "ADDITIONAL_SECURITY";1564-
1572-1565- pane_widget.show_all();
1573- default:1566-
1574- error("unrecognized CredentialsPane.Mode enumeration value");1567- on_entry_contents_changed();
1575- }1568- }
1576- }1569-
1577- }1570- private void on_continue_clicked() {
1578-1571- proceed(this, entry.get_text());
1579- private LegacyCredentialsPane wrapped = null;1572- }
1580-1573-
1581- public signal void go_back();1574- private void on_entry_contents_changed() {
1582- public signal void login(string email, string password);1575- continue_button.set_sensitive(entry.text_length > 0);
1583-
1584- public CredentialsPane(Spit.Publishing.PluginHost host, Mode mode = Mode.INTRO,
1585- string? username = null) {
1586- wrapped = new LegacyCredentialsPane(host, mode, username);
1587- }
1588-
1589- protected void notify_go_back() {
1590- go_back();
1591- }
1592-
1593- protected void notify_login(string email, string password) {
1594- login(email, password);
1595- }1576- }
1596-1577-
1597- public Gtk.Widget get_widget() {1578- public Gtk.Widget get_widget() {
1598- return wrapped;1579- return pane_widget;
1599- }1580- }
1600- 1581-
1601- public Spit.Publishing.DialogPane.GeometryOptions get_preferred_geometry() {1582- public Spit.Publishing.DialogPane.GeometryOptions get_preferred_geometry() {
1602- return Spit.Publishing.DialogPane.GeometryOptions.NONE;1583- return Spit.Publishing.DialogPane.GeometryOptions.NONE;
1603- }1584- }
1604- 1585-
1605- public void on_pane_installed() { 1586- public void on_pane_installed() {
1606- wrapped.go_back.connect(notify_go_back);1587- continue_button.clicked.connect(on_continue_clicked);
1607- wrapped.login.connect(notify_login);1588- entry.changed.connect(on_entry_contents_changed);
1608-
1609- wrapped.installed();
1610- }1589- }
1611- 1590-
1612- public void on_pane_uninstalled() {1591- public void on_pane_uninstalled() {
1613- wrapped.go_back.disconnect(notify_go_back);1592- continue_button.clicked.disconnect(on_continue_clicked);
1614- wrapped.login.disconnect(notify_login);1593- entry.changed.disconnect(on_entry_contents_changed);
1615- }1594- }
1616-}1595-}
1617-1596-
1618-internal class LegacyCredentialsPane : Gtk.VBox {1597-internal class NotSetUpMessagePane : Spit.Publishing.DialogPane, GLib.Object {
1619- private const string INTRO_MESSAGE = _("Enter the email address and password associated with your Picasa Web Albums account.");1598- private Gtk.Box pane_widget = null;
1620- private const string FAILED_RETRY_MESSAGE = _("Picasa Web Albums didn't recognize the email address and password you entered. To try again, re-enter your email address and password below.");1599- private Gtk.Button continue_button = null;
1621- private const string NOT_SET_UP_MESSAGE = _("The email address and password you entered correspond to a Google account that isn't set up for use with Picasa Web Albums. You can set up most accounts by using your browser to log into the Picasa Web Albums site at least once. To try again, re-enter your email address and password below.");1600-
1622- private const string ADDITIONAL_SECURITY_MESSAGE = _("The email address and password you entered correspond to a Google account that has been tagged as requiring additional security. You can clear this tag by using your browser to log into Picasa Web Albums. To try again, re-enter your email address and password below.");1601- public signal void proceed(NotSetUpMessagePane sender);
1623- 1602-
1624- private const int UNIFORM_ACTION_BUTTON_WIDTH = 102;1603- public NotSetUpMessagePane(Gtk.Builder builder) {
1625- private const int VERTICAL_SPACE_HEIGHT = 32;1604- assert(builder != null);
1626- public const int STANDARD_CONTENT_LABEL_WIDTH = 500;1605- assert(builder.get_objects().length() > 0);
1627-1606-
1628- private weak Spit.Publishing.PluginHost host = null;1607- continue_button = builder.get_object("continue_button") as Gtk.Button;
1629- private Gtk.Entry email_entry;1608- pane_widget = builder.get_object("pane_widget") as Gtk.Box;
1630- private Gtk.Entry password_entry;1609-
1631- private Gtk.Button login_button;1610- pane_widget.show_all();
1632- private Gtk.Button go_back_button;1611- }
1633- private string? username = null;1612-
1634-1613- private void on_continue_clicked() {
1635- public signal void go_back();1614- proceed(this);
1636- public signal void login(string email, string password);1615- }
1637-1616-
1638- public LegacyCredentialsPane(Spit.Publishing.PluginHost host, CredentialsPane.Mode mode =1617- public Gtk.Widget get_widget() {
1639- CredentialsPane.Mode.INTRO, string? username = null) {1618- return pane_widget;
1640- this.host = host;1619- }
1641- this.username = username;1620-
1642-1621- public Spit.Publishing.DialogPane.GeometryOptions get_preferred_geometry() {
1643- add(gtk_vspacer(VERTICAL_SPACE_HEIGHT));1622- return Spit.Publishing.DialogPane.GeometryOptions.NONE;
1644-1623- }
1645- Gtk.Label intro_message_label = new Gtk.Label("");1624-
1646- intro_message_label.set_line_wrap(true);1625- public void on_pane_installed() {
1647- add(intro_message_label);1626- continue_button.clicked.connect(on_continue_clicked);
1648- intro_message_label.set_size_request(STANDARD_CONTENT_LABEL_WIDTH, -1);1627- }
1649- intro_message_label.set_alignment(0.5f, 0.0f);1628-
1650- switch (mode) {1629- public void on_pane_uninstalled() {
1651- case CredentialsPane.Mode.INTRO:1630- continue_button.clicked.disconnect(on_continue_clicked);
1652- intro_message_label.set_text(INTRO_MESSAGE);
1653- break;
1654-
1655- case CredentialsPane.Mode.FAILED_RETRY:
1656- intro_message_label.set_markup("<b>%s</b>\n\n%s".printf(_(
1657- "Unrecognized User"), FAILED_RETRY_MESSAGE));
1658- break;
1659-
1660- case CredentialsPane.Mode.NOT_SET_UP:
1661- intro_message_label.set_markup("<b>%s</b>\n\n%s".printf(_("Account Not Ready"),
1662- NOT_SET_UP_MESSAGE));
1663- add(gtk_vspacer(VERTICAL_SPACE_HEIGHT));
1664- break;
1665-
1666- case CredentialsPane.Mode.ADDITIONAL_SECURITY:
1667- intro_message_label.set_markup("<b>%s</b>\n\n%s".printf(_("Additional Security Required"),
1668- ADDITIONAL_SECURITY_MESSAGE));
1669- add(gtk_vspacer(VERTICAL_SPACE_HEIGHT));
1670- break;
1671- }
1672-
1673- Gtk.Alignment entry_widgets_table_aligner = new Gtk.Alignment(0.5f, 0.5f, 0.0f, 0.0f);
1674- Gtk.Table entry_widgets_table = new Gtk.Table(3,2, false);
1675- Gtk.Label email_entry_label = new Gtk.Label.with_mnemonic(_("_Email address:"));
1676- email_entry_label.set_alignment(0.0f, 0.5f);
1677- Gtk.Label password_entry_label = new Gtk.Label.with_mnemonic(_("_Password:"));
1678- password_entry_label.set_alignment(0.0f, 0.5f);
1679- email_entry = new Gtk.Entry();
1680- if (username != null)
1681- email_entry.set_text(username);
1682- email_entry.changed.connect(on_email_changed);
1683- password_entry = new Gtk.Entry();
1684- password_entry.set_visibility(false);
1685- entry_widgets_table.attach(email_entry_label, 0, 1, 0, 1,
1686- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL,
1687- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 6, 6);
1688- entry_widgets_table.attach(password_entry_label, 0, 1, 1, 2,
1689- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL,
1690- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 6, 6);
1691- entry_widgets_table.attach(email_entry, 1, 2, 0, 1,
1692- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL,
1693- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 6, 6);
1694- entry_widgets_table.attach(password_entry, 1, 2, 1, 2,
1695- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL,
1696- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 6, 6);
1697- go_back_button = new Gtk.Button.with_mnemonic(_("Go _Back"));
1698- go_back_button.clicked.connect(on_go_back_button_clicked);
1699- Gtk.Alignment go_back_button_aligner = new Gtk.Alignment(0.0f, 0.5f, 0.0f, 0.0f);
1700- go_back_button_aligner.add(go_back_button);
1701- go_back_button.set_size_request(UNIFORM_ACTION_BUTTON_WIDTH, -1);
1702- login_button = new Gtk.Button.with_mnemonic(_("_Login"));
1703- login_button.clicked.connect(on_login_button_clicked);
1704- login_button.set_sensitive(username != null);
1705- Gtk.Alignment login_button_aligner = new Gtk.Alignment(1.0f, 0.5f, 0.0f, 0.0f);
1706- login_button_aligner.add(login_button);
1707- login_button.set_size_request(UNIFORM_ACTION_BUTTON_WIDTH, -1);
1708- entry_widgets_table.attach(go_back_button_aligner, 0, 1, 2, 3,
1709- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL,
1710- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 6, VERTICAL_SPACE_HEIGHT);
1711- entry_widgets_table.attach(login_button_aligner, 1, 2, 2, 3,
1712- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL,
1713- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 6, VERTICAL_SPACE_HEIGHT);
1714- entry_widgets_table_aligner.add(entry_widgets_table);
1715- add(entry_widgets_table_aligner);
1716-
1717- email_entry_label.set_mnemonic_widget(email_entry);
1718- password_entry_label.set_mnemonic_widget(password_entry);
1719-
1720- add(gtk_vspacer(VERTICAL_SPACE_HEIGHT));
1721- }
1722-
1723- private void on_login_button_clicked() {
1724- login(email_entry.get_text(), password_entry.get_text());
1725- }
1726-
1727- private void on_go_back_button_clicked() {
1728- go_back();
1729- }
1730-
1731- private void on_email_changed() {
1732- login_button.set_sensitive(email_entry.get_text() != "");
1733- }
1734-
1735- public void installed() {
1736- host.set_service_locked(false);
1737-
1738- email_entry.grab_focus();
1739- password_entry.set_activates_default(true);
1740- login_button.can_default = true;
1741- host.set_dialog_default_widget(login_button);
1742- }1631- }
1743-}1632-}
1744-1633-
1745 internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object {1634 internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object {
1746 private LegacyPublishingOptionsPane wrapped = null;1635 private class SizeDescription {
1747 1636 public string name;
1748
1749Index: shotwell-0.12.90/src/plugins/PublishingInterfaces.vala1637Index: shotwell-0.12.90/src/plugins/PublishingInterfaces.vala
1750===================================================================1638===================================================================
1751--- shotwell-0.12.90.orig/src/plugins/PublishingInterfaces.vala 2012-08-24 09:03:04.000000000 +12001639--- shotwell-0.12.90.orig/src/plugins/PublishingInterfaces.vala 2012-08-24 00:03:04.000000000 +0300
1752+++ shotwell-0.12.90/src/plugins/PublishingInterfaces.vala 2012-08-24 15:15:23.971988123 +12001640+++ shotwell-0.12.90/src/plugins/PublishingInterfaces.vala 2012-08-28 10:25:15.300033478 +0300
1753@@ -494,6 +494,7 @@1641@@ -494,6 +494,7 @@
1754 */1642 */
1755 public abstract Spit.Publishing.Publisher.MediaType get_publishable_media_type();1643 public abstract Spit.Publishing.Publisher.MediaType get_publishable_media_type();
@@ -1776,8 +1664,8 @@
1776 protected virtual void reserved3() {}1664 protected virtual void reserved3() {}
1777Index: shotwell-0.12.90/src/publishing/PublishingPluginHost.vala1665Index: shotwell-0.12.90/src/publishing/PublishingPluginHost.vala
1778===================================================================1666===================================================================
1779--- shotwell-0.12.90.orig/src/publishing/PublishingPluginHost.vala 2012-08-24 09:03:04.000000000 +12001667--- shotwell-0.12.90.orig/src/publishing/PublishingPluginHost.vala 2012-08-24 00:03:04.000000000 +0300
1780+++ shotwell-0.12.90/src/publishing/PublishingPluginHost.vala 2012-08-24 15:15:23.971988123 +12001668+++ shotwell-0.12.90/src/publishing/PublishingPluginHost.vala 2012-08-28 10:25:15.300033478 +0300
1781@@ -232,6 +232,13 @@1669@@ -232,6 +232,13 @@
1782 1670
1783 return report_plugin_upload_progress;1671 return report_plugin_upload_progress;
@@ -1794,8 +1682,8 @@
1794 }1682 }
1795Index: shotwell-0.12.90/src/publishing/PublishingUI.vala1683Index: shotwell-0.12.90/src/publishing/PublishingUI.vala
1796===================================================================1684===================================================================
1797--- shotwell-0.12.90.orig/src/publishing/PublishingUI.vala 2012-08-24 09:03:04.000000000 +12001685--- shotwell-0.12.90.orig/src/publishing/PublishingUI.vala 2012-08-24 00:03:04.000000000 +0300
1798+++ shotwell-0.12.90/src/publishing/PublishingUI.vala 2012-08-24 15:15:23.971988123 +12001686+++ shotwell-0.12.90/src/publishing/PublishingUI.vala 2012-08-28 10:25:15.300033478 +0300
1799@@ -296,6 +296,7 @@1687@@ -296,6 +296,7 @@
1800 Spit.Publishing.Service[] all_services = load_all_services();1688 Spit.Publishing.Service[] all_services = load_all_services();
1801 1689

Subscribers

People subscribed via source and target branches