[Commits] [SCM] claws branch, master, updated. 4.1.0-30-ge4e359121

miras at claws-mail.org miras at claws-mail.org
Thu May 26 22:10:02 UTC 2022


The branch, master has been updated
       via  e4e3591217a6e841ab51cb1c398efb3c6b0b3482 (commit)
      from  98d87a84cf8dab0c8bdd30e33779f59f7b1dc5a7 (commit)

Summary of changes:
 src/prefs_account.c | 216 ++++++++++++++++++++++++++++------------------------
 1 file changed, 116 insertions(+), 100 deletions(-)


- Log -----------------------------------------------------------------
commit e4e3591217a6e841ab51cb1c398efb3c6b0b3482
Author: Michael Rasmussen <mir at datanom.net>
Date:   Fri May 27 00:09:37 2022 +0200

    Improved OAuth solution from David Fletcher
    
    Signed-off-by: Michael Rasmussen <mir at datanom.net>

diff --git a/src/prefs_account.c b/src/prefs_account.c
index 802bf4584..3283c1b30 100644
--- a/src/prefs_account.c
+++ b/src/prefs_account.c
@@ -73,7 +73,6 @@
 #ifdef USE_GNUTLS
 #include <gnutls/gnutls.h>
 #endif
-#include <pthread.h> 
 
 static gboolean cancelled;
 static gboolean new_account;
@@ -101,8 +100,9 @@ struct AutocheckWidgets {
 
 static GSList *prefs_pages = NULL;
 
-static pthread_t oauth2_listener_tid;
+static GTask *oauth2_listener_task;
 static int oauth2_listener_cancel = 0;
+static int oauth2_listener_closed = 0;
 
 typedef struct BasicPage
 {
@@ -408,6 +408,13 @@ static char *protocol_names[] = {
 	N_("None (SMTP only)")
 };
 
+struct Oauth2Listener {
+	int success;
+  	Oauth2Service service;
+        OAUTH2Data *OAUTH2Data;
+        gchar *trim_text;
+};
+
 static void prefs_account_protocol_set_data_from_optmenu(PrefParam *pparam);
 static void prefs_account_protocol_set_optmenu		(PrefParam *pparam);
 static void prefs_account_protocol_changed		(GtkComboBox *combobox,
@@ -431,7 +438,8 @@ static void prefs_account_oauth2_provider_set_data_from_optmenu
 static void prefs_account_oauth2_provider_set_optmenu	(PrefParam *pparam);
 static void prefs_account_oauth2_copy_url                       (GtkButton *button, 
 							 gpointer data);
-static void * prefs_account_oauth2_listener(void *params);
+static void prefs_account_oauth2_listener(GTask *task, gpointer source, gpointer task_data, GCancellable *cancellable);
+static void prefs_account_oauth2_callback(GObject *source, GAsyncResult *res, gpointer user_data);
 static int  prefs_account_oauth2_get_line(int sock, char *buf, int size);
 static void prefs_account_oauth2_set_sensitivity(void);
 static void prefs_account_oauth2_set_auth_sensitivity(void);
@@ -3788,11 +3796,9 @@ static void oauth2_destroy_widget_func(PrefsPage *_page)
 {
 	/* Oauth2Page *page = (Oauth2Page *) _page; */
 
-        if(oauth2_listener_tid){
-	  debug_print("Closing oauth2 listener thread\n");
+        if(oauth2_listener_task){
+	  debug_print("Closing oauth2 listener task\n");
 	  oauth2_listener_cancel = 1;
-	  pthread_join(oauth2_listener_tid, NULL);
-	  oauth2_listener_tid = (pthread_t)NULL;
 	}
 }
 
@@ -4122,9 +4128,7 @@ static void register_oauth2_page(void)
 	oauth2_page.page.destroy_widget = oauth2_destroy_widget_func;
 	oauth2_page.page.save_page = oauth2_save_func;
 	oauth2_page.page.can_close = oauth2_can_close_func;
-
-	oauth2_listener_tid = (pthread_t)NULL;
-
+	  
 	prefs_account_register_page((PrefsPage *) &oauth2_page);
 }
 
@@ -5113,17 +5117,16 @@ static void prefs_account_oauth2_copy_url(GtkButton *button, gpointer data)
 	url = g_malloc(OAUTH2BUFSIZE+1);
 	Oauth2Service service;
 	const gchar * custom_client_id = NULL;
-	int ret;
-
+	struct Oauth2Listener *oauth2_listener_data;
+		
 	service = combobox_get_active_data(GTK_COMBO_BOX(optmenu));
-
 	custom_client_id = gtk_entry_get_text((GtkEntry *)oauth2_page.oauth2_client_id_entry);
-
+	
 	oauth2_authorisation_url(service, &url, custom_client_id);
-
+	
 	win = gtk_widget_get_toplevel (optmenu);
 	len = strlen(url);
-
+       
 	clip = gtk_widget_get_clipboard (win, GDK_SELECTION_PRIMARY);
 	clip2 = gtk_widget_get_clipboard (win, GDK_SELECTION_CLIPBOARD);
 	gtk_clipboard_set_text (clip, url, len);
@@ -5134,22 +5137,35 @@ static void prefs_account_oauth2_copy_url(GtkButton *button, gpointer data)
 
 	g_free(url);
 
-	//Start listener for authorisation reply
-	//Needs to be in a separate thread to avoid hanging while we wait, and to allow cancellation of the process
-	//Avoid starting multiple threads if someone clicks this button more than once. 
-
-	//if thead exists cancel it here
-	if(oauth2_listener_tid){
-	  debug_print("Cancelling old oauth2 listener thread\n");
+	//Start listener task for authorisation reply using a separate task
+	//Avoids hanging while we wait, and to allow cancellation of the process
+	//If task already exists gracefully close it
+	if(oauth2_listener_task){
+	  debug_print("Closing oauth2 listener task\n");
 	  oauth2_listener_cancel = 1;
-	  pthread_join(oauth2_listener_tid, NULL);
-	  oauth2_listener_tid = (pthread_t)NULL;
+	  while (oauth2_listener_closed == 0)
+	    gtk_main_iteration();
 	}
-	debug_print("Starting oauth2 listener thread\n");
+		
+	debug_print("Starting oauth2 listener task\n");
+
+	oauth2_listener_data = g_new(struct Oauth2Listener, 1);
+	oauth2_listener_data->success = FALSE;
+	oauth2_listener_data->trim_text = NULL;
+	oauth2_listener_data->service = combobox_get_active_data(GTK_COMBO_BOX(optmenu));
+	oauth2_listener_data->OAUTH2Data = g_malloc(sizeof(* oauth2_listener_data->OAUTH2Data));
+	oauth2_init (oauth2_listener_data->OAUTH2Data);
+	oauth2_listener_data->OAUTH2Data->custom_client_secret = 
+		    g_strdup(gtk_entry_get_text((GtkEntry *)oauth2_page.oauth2_client_secret_entry));
+	oauth2_listener_data->OAUTH2Data->custom_client_id = 
+		    g_strdup(gtk_entry_get_text((GtkEntry *)oauth2_page.oauth2_client_id_entry));
+
 	oauth2_listener_cancel = 0;
-	ret = pthread_create(&oauth2_listener_tid, NULL, prefs_account_oauth2_listener, NULL);
-	if (ret != 0)
-		g_warning("can't create thread: %d", ret);
+	oauth2_listener_closed = 0;
+	
+	oauth2_listener_task = g_task_new(NULL, NULL, prefs_account_oauth2_callback, oauth2_listener_data);
+	g_task_set_task_data(oauth2_listener_task, oauth2_listener_data, NULL);
+	g_task_run_in_thread(oauth2_listener_task, prefs_account_oauth2_listener);
 }
 
 static void prefs_account_oauth2_obtain_tokens(GtkButton *button, gpointer data)
@@ -6016,32 +6032,27 @@ static void prefs_account_receive_itv_spinbutton_value_changed_cb(GtkWidget *w,
 }
 
 //Automation of the oauth2 authorisation process to receive loopback callback generated by redirect in browser
-static void * prefs_account_oauth2_listener(void * param)
-{ 
+static void prefs_account_oauth2_listener(GTask *task, gpointer source, gpointer task_data, GCancellable *cancellable)
+{
+        struct Oauth2Listener *oauth2_listener_data = (struct Oauth2Listener *)task_data;
         int socket_desc, client_sock, c;
 	struct sockaddr_in server , client;
 	char client_message[2000];
 	char reply[600];
 	char reply_message[400];
-	gchar *trim_text = NULL;
 	fd_set rfds;
-	gint ret;
+	gint ret = 1;
 	struct timeval timeout;
-	struct BasicProtocol *protocol_optmenu = (struct BasicProtocol *)oauth2_page.protocol_optmenu;
-	GtkWidget *optmenu = protocol_optmenu->combobox;
-	Oauth2Service service;
-        OAUTH2Data *OAUTH2Data = NULL;
 
-	
-	//pthread_detach(pthread_self());
-	debug_print("oauth2 listener thread running\n");
+	debug_print("oauth2 listener task running\n");
      
 	//Create socket
 	socket_desc = socket(AF_INET , SOCK_STREAM , 0);
 	if (socket_desc == -1)
 	{
 		debug_print("oauth2 listener could not create socket\n");
-		return NULL;
+		g_task_return_boolean (task, TRUE);
+		g_object_unref (task);
 	}
 	debug_print("oauth2 listener socket created\n");
 	
@@ -6055,7 +6066,8 @@ static void * prefs_account_oauth2_listener(void * param)
 	{
                 close(socket_desc);
 		debug_print("oauth2 listener bind failed\n");
-		return NULL;
+		g_task_return_boolean (task, TRUE);
+		g_object_unref (task);
 	}
 	debug_print("oauth2 listener bind done\n");
 
@@ -6079,65 +6091,20 @@ static void * prefs_account_oauth2_listener(void * param)
 	          client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
 		  if (client_sock < 0){
 		    debug_print("oauth2 listener accept failed\n");
-		    return NULL;
+		    g_task_return_boolean (task, TRUE);
+		    g_object_unref (task);
 		  }
 		  debug_print("oauth2 listener connection accepted\n");
 		  
 		  //Receive message sent to the loopback address by the authorisation page
 		  prefs_account_oauth2_get_line(client_sock, client_message, sizeof(client_message));
-		  trim_text = g_strdup(client_message);
-		  g_strstrip(trim_text);
+		  oauth2_listener_data->trim_text = g_strdup(client_message);
+		  g_strstrip(oauth2_listener_data->trim_text);
 
-		  gtk_entry_set_text(GTK_ENTRY(oauth2_page.oauth2_authcode_entry), trim_text != NULL ? trim_text : "");
-		  gtk_widget_set_sensitive(oauth2_page.oauth2_authcode_entry, FALSE);
-		  gtk_widget_set_sensitive(oauth2_page.oauth2_authorise_btn, FALSE);
-		  
-                  OAUTH2Data = g_malloc(sizeof(* OAUTH2Data));
-		  oauth2_init (OAUTH2Data);
-		  
-		  OAUTH2Data->custom_client_secret = 
-		    g_strdup(gtk_entry_get_text((GtkEntry *)oauth2_page.oauth2_client_secret_entry));
-		  OAUTH2Data->custom_client_id = 
-		    g_strdup(gtk_entry_get_text((GtkEntry *)oauth2_page.oauth2_client_id_entry));
-		  
-		  service = combobox_get_active_data(GTK_COMBO_BOX(optmenu));
-		  ret = oauth2_obtain_tokens (service, OAUTH2Data, trim_text);
+		  ret = oauth2_obtain_tokens (oauth2_listener_data->service, oauth2_listener_data->OAUTH2Data, oauth2_listener_data->trim_text);
 		  
 		  if(!ret){
-		    if(OAUTH2Data->refresh_token != NULL){
-		      passwd_store_set_account(tmp_ac_prefs.account_id,
-					       PWS_ACCOUNT_OAUTH2_REFRESH,
-					       OAUTH2Data->refresh_token,
-					       FALSE);
-		      log_message(LOG_PROTOCOL, "OAuth2 refresh token stored\n");
-		    }
-		    
-		    if(OAUTH2Data->access_token != NULL){
-		      passwd_store_set_account(tmp_ac_prefs.account_id,
-					       PWS_ACCOUNT_RECV,
-					       OAUTH2Data->access_token,
-					       FALSE);
-		      
-		      passwd_store_set_account(tmp_ac_prefs.account_id,
-					       PWS_ACCOUNT_SEND,
-					       OAUTH2Data->access_token,
-					       FALSE);
-		      log_message(LOG_PROTOCOL, "OAuth2 access token stored\n");
-		      
-		      gtk_entry_set_text(GTK_ENTRY(basic_page.pass_entry), OAUTH2Data->access_token);
-		      gtk_entry_set_text(GTK_ENTRY(send_page.smtp_pass_entry), OAUTH2Data->access_token);
-		    }
-		    
-		    if(OAUTH2Data->expiry_str != NULL){
-		      passwd_store_set_account(tmp_ac_prefs.account_id,
-					       PWS_ACCOUNT_OAUTH2_EXPIRY,
-					       OAUTH2Data->expiry_str,
-					       FALSE);
-		      log_message(LOG_PROTOCOL, "OAuth2 access token expiry stored\n");
-		    }
-		    
-		    tmp_ac_prefs.oauth2_date = g_get_real_time () / G_USEC_PER_SEC;
-		    
+		    oauth2_listener_data->success = TRUE;
 		    sprintf(reply_message, "<html><body><h1>Authorisation complete</h1><p>Your oauth2 authorisation code has been received by Claws Mail</p></body></html>");
 		  }else{
 		    //Something went wrong
@@ -6153,15 +6120,64 @@ static void * prefs_account_oauth2_listener(void * param)
 	}while(ret && !oauth2_listener_cancel);
 
 	close(socket_desc);
-	g_free(trim_text);
-	g_free(OAUTH2Data);
-	
-	return NULL;
+	debug_print("oauth2 closing task\n");
+	g_task_return_boolean (task, TRUE);
+	g_object_unref (task);
 }
 
-
-
-
+static void prefs_account_oauth2_callback(GObject *source, GAsyncResult *res, gpointer user_data)
+{
+       struct Oauth2Listener *oauth2_listener_data = (struct Oauth2Listener *)user_data;
+       
+       if(oauth2_listener_data->success){
+	 debug_print("oauth2 listener callback storing data and updating GUI\n");
+	 
+	 if(oauth2_listener_data->OAUTH2Data->refresh_token != NULL){
+	   passwd_store_set_account(tmp_ac_prefs.account_id,
+				    PWS_ACCOUNT_OAUTH2_REFRESH,
+				    oauth2_listener_data->OAUTH2Data->refresh_token,
+				    FALSE);
+	   log_message(LOG_PROTOCOL, "OAuth2 refresh token stored\n");
+	 }
+	 
+	 if(oauth2_listener_data->OAUTH2Data->access_token != NULL){
+	   passwd_store_set_account(tmp_ac_prefs.account_id,
+				    PWS_ACCOUNT_RECV,
+				    oauth2_listener_data->OAUTH2Data->access_token,
+				    FALSE);
+	   
+	   passwd_store_set_account(tmp_ac_prefs.account_id,
+				    PWS_ACCOUNT_SEND,
+				    oauth2_listener_data->OAUTH2Data->access_token,
+				    FALSE);
+	   log_message(LOG_PROTOCOL, "OAuth2 access token stored\n");
+	   
+	 }
+	 
+	 if(oauth2_listener_data->OAUTH2Data->expiry_str != NULL){
+	   passwd_store_set_account(tmp_ac_prefs.account_id,
+				    PWS_ACCOUNT_OAUTH2_EXPIRY,
+				    oauth2_listener_data->OAUTH2Data->expiry_str,
+				    FALSE);
+	   log_message(LOG_PROTOCOL, "OAuth2 access token expiry stored\n");
+	 }
+	 
+	 tmp_ac_prefs.oauth2_date = g_get_real_time () / G_USEC_PER_SEC;
+	 
+	 gtk_entry_set_text(GTK_ENTRY(oauth2_page.oauth2_authcode_entry), oauth2_listener_data->trim_text != NULL ? oauth2_listener_data->trim_text : "");
+	 gtk_widget_set_sensitive(oauth2_page.oauth2_authcode_entry, FALSE);
+	 gtk_widget_set_sensitive(oauth2_page.oauth2_authorise_btn, FALSE);
+	 gtk_entry_set_text(GTK_ENTRY(basic_page.pass_entry), oauth2_listener_data->OAUTH2Data->access_token);
+	 gtk_entry_set_text(GTK_ENTRY(send_page.smtp_pass_entry), oauth2_listener_data->OAUTH2Data->access_token); 
+       }
+       
+       debug_print("oauth2 listener callback freeing resources\n");
+       g_free(oauth2_listener_data->trim_text);
+       g_free(oauth2_listener_data->OAUTH2Data);
+       g_free(oauth2_listener_data);
+       oauth2_listener_cancel = 0;
+       oauth2_listener_closed = 1; 
+}
 
 static int prefs_account_oauth2_get_line(int sock, char *buf, int size)
 {

-----------------------------------------------------------------------


hooks/post-receive
-- 
Claws Mail


More information about the Commits mailing list