Make GData plugin use the password store.
[claws.git] / src / plugins / gdata / cm_gdata_contacts.c
index b8175e6..86fc265 100644 (file)
@@ -1,5 +1,6 @@
 /* GData plugin for Claws-Mail
  * Copyright (C) 2011 Holger Berndt
+ * Copyright (C) 2011-2015 the Claws Mail team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -30,6 +31,7 @@
 
 #include "addr_compl.h"
 #include "main.h"
+#include "passwordstore.h"
 #include "prefs_common.h"
 #include "mainwindow.h"
 #include "common/log.h"
@@ -239,12 +241,12 @@ static void write_cache_to_file(void)
     g_node_append(contactsnode, contactnode);
   }
 
-  /* Actual writing and cleanup */
-  xml_write_tree(rootnode, pfile->fp);
-  if(prefs_file_close(pfile) < 0)
-    debug_print("GData plugin error: Failed to write file " GDATA_CONTACTS_FILENAME "\n");
-
-  debug_print("GData plugin error: Wrote cache to file " GDATA_CONTACTS_FILENAME "\n");
+       /* Actual writing and cleanup */
+       xml_write_tree(rootnode, pfile->fp);
+       if (prefs_file_close(pfile) < 0)
+               debug_print("GData plugin error: Failed to write file " GDATA_CONTACTS_FILENAME "\n");
+       else
+               debug_print("GData plugin: Wrote cache to file " GDATA_CONTACTS_FILENAME "\n");
 
   /* Free XML tree */
   xml_free_tree(rootnode);
@@ -336,9 +338,9 @@ static void cm_gdata_query_contacts_ready(GDataContactsService *service, GAsyncR
   }
   g_object_unref(feed);
   contacts_cache.contacts = g_slist_reverse(contacts_cache.contacts);
-       /* i18n: First part of "Added X of Y contacts to cache" */
+       /* TRANSLATORS: First part of "Added X of Y contacts to cache" */
   tmpstr1 = g_strdup_printf(ngettext("Added %d of", "Added %d of", num_contacts_added), num_contacts_added);
-       /* i18n: Second part of "Added X of Y contacts to cache" */
+       /* TRANSLATORS: Second part of "Added X of Y contacts to cache" */
   tmpstr2 = g_strdup_printf(ngettext("1 contact to the cache", "%d contacts to the cache", num_contacts), num_contacts);
   log_message(LOG_PROTOCOL, "%s %s\n", tmpstr1, tmpstr2);
        g_free(tmpstr1);
@@ -430,11 +432,11 @@ static void query_after_auth()
 }
 
 
-static void cm_gdata_auth_ready(GDataOAuth2Authorizer *authorizer, GAsyncResult *res, gpointer data)
+static void cm_gdata_auth_ready(GDataOAuth2Authorizer *auth, GAsyncResult *res, gpointer data)
 {
   GError *error = NULL;
 
-  if(gdata_oauth2_authorizer_request_authorization_finish(authorizer, res, &error) == FALSE)
+  if(gdata_oauth2_authorizer_request_authorization_finish(auth, res, &error) == FALSE)
   {
     /* Notify the user of all errors except cancellation errors */
     if(!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
@@ -451,6 +453,61 @@ static void cm_gdata_auth_ready(GDataOAuth2Authorizer *authorizer, GAsyncResult
   query_after_auth();
 }
 
+static void cm_gdata_interactive_auth()
+{
+  gchar *auth_uri;
+  gchar *auth_code;
+
+  log_message(LOG_PROTOCOL, _("GData plugin: Starting interactive authorization\n"));
+
+  auth_uri = gdata_oauth2_authorizer_build_authentication_uri(authorizer, cm_gdata_config.username, FALSE);
+  g_return_if_fail(auth_uri);
+
+  auth_code = ask_user_for_auth_code(auth_uri);
+
+  if(auth_code)
+  {
+    cm_gdata_contacts_query_running = TRUE;
+    log_message(LOG_PROTOCOL, _("GData plugin: Got authorization code, requesting authorization\n"));
+    gdata_oauth2_authorizer_request_authorization_async(authorizer, auth_code, NULL, (GAsyncReadyCallback)cm_gdata_auth_ready, NULL);
+    memset(auth_code, 0, strlen(auth_code));
+    g_free(auth_code);
+  }
+  else
+  {
+    log_warning(LOG_PROTOCOL, _("GData plugin: No authorization code received, authorization request cancelled\n"));
+  }
+
+  g_free(auth_uri);
+}
+
+
+#if GDATA_CHECK_VERSION(0,17,2)
+static void cm_gdata_refresh_ready(GDataOAuth2Authorizer *auth, GAsyncResult *res, gpointer data)
+{
+  GError *error = NULL;
+
+  if(gdata_authorizer_refresh_authorization_finish(GDATA_AUTHORIZER(auth), res, &error) == FALSE)
+  {
+    /* Notify the user of all errors except cancellation errors */
+    if(!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+    {
+      log_error(LOG_PROTOCOL, _("GData plugin: Authorization refresh error: %s\n"), error->message);
+    }
+    g_error_free(error);
+
+    cm_gdata_interactive_auth();
+
+    return;
+  }
+
+  log_message(LOG_PROTOCOL, _("GData plugin: Authorization refresh successful\n"));
+
+  query_after_auth();
+}
+#endif
+
+
 /* returns allocated string which must be freed */
 static guchar* decode(const gchar *in)
 {
@@ -462,10 +519,10 @@ static guchar* decode(const gchar *in)
   return tmp;
 }
 
+
 static void query()
 {
-  gchar *auth_uri;
-  gchar *auth_code;
+       gchar *token;
 
   if(cm_gdata_contacts_query_running)
   {
@@ -495,27 +552,24 @@ static void query()
 
   if(!gdata_service_is_authorized(GDATA_SERVICE(service)))
   {
-    log_message(LOG_PROTOCOL, _("GData plugin: Starting async authorization\n"));
-
-    auth_uri = gdata_oauth2_authorizer_build_authentication_uri(authorizer, cm_gdata_config.username, FALSE);
-    g_return_if_fail(auth_uri);
-
-    auth_code = ask_user_for_auth_code(auth_uri);
-
-    if(auth_code)
+#if GDATA_CHECK_VERSION(0,17,2)
+    /* Try to restore from saved refresh token.*/
+               if((token = passwd_store_get(PWS_PLUGIN,
+                                               "GData", GDATA_TOKEN_PWD_STRING)) != NULL)
     {
-      cm_gdata_contacts_query_running = TRUE;
-      log_message(LOG_PROTOCOL, _("GData plugin: Got authorization code, requesting authorization\n"));
-      gdata_oauth2_authorizer_request_authorization_async(authorizer, auth_code, NULL, (GAsyncReadyCallback)cm_gdata_auth_ready, NULL);
-      memset(auth_code, 0, strlen(auth_code));
-      g_free(auth_code);
+      log_message(LOG_PROTOCOL, _("GData plugin: Trying to refresh authorization\n"));
+      gdata_oauth2_authorizer_set_refresh_token(authorizer, token);
+      memset(token, 0, strlen(token));
+      g_free(token);
+      gdata_authorizer_refresh_authorization_async(GDATA_AUTHORIZER(authorizer), NULL, (GAsyncReadyCallback)cm_gdata_refresh_ready, NULL);
     }
     else
     {
-      log_warning(LOG_PROTOCOL, _("GData plugin: No authorization code received, authorization request cancelled\n"));
+      cm_gdata_interactive_auth();
     }
-
-    g_free(auth_uri);
+#else
+    cm_gdata_interactive_auth();
+#endif
   }
   else
   {
@@ -556,7 +610,7 @@ void cm_gdata_add_contacts(GList **address_list)
 
 gboolean cm_gdata_update_contacts_cache(void)
 {
-  if(prefs_common.work_offline)
+  if(prefs_common_get_prefs()->work_offline)
   {
     debug_print("GData plugin: Offline mode\n");
   }
@@ -570,6 +624,8 @@ gboolean cm_gdata_update_contacts_cache(void)
 
 void cm_gdata_contacts_done(void)
 {
+  gchar *pass;
+
   g_free(contacts_group_id);
   contacts_group_id = NULL;
 
@@ -579,6 +635,15 @@ void cm_gdata_contacts_done(void)
 
   if(authorizer)
   {
+#if GDATA_CHECK_VERSION(0,17,2)
+    /* store refresh token */
+    pass = gdata_oauth2_authorizer_dup_refresh_token(authorizer);
+               passwd_store_set(PWS_PLUGIN, "GData", GDATA_TOKEN_PWD_STRING, pass,
+                               FALSE);
+    memset(pass, 0, strlen(pass));
+    g_free(pass);
+#endif
+
     g_object_unref(G_OBJECT(authorizer));
     authorizer = NULL;
   }
@@ -613,7 +678,7 @@ void cm_gdata_load_contacts_cache_from_file(void)
 
   /* Check that root entry is "gdata" */
   if(strcmp2(xmlnode->tag->tag, "gdata") != 0) {
-    g_warning("wrong gdata cache file\n");
+    g_warning("wrong gdata cache file");
     xml_free_tree(rootnode);
     return;
   }