/cpw/tomkiewicz/masterpassword: e9722a935271: Re-implemented GNO...

Tomasz Wasilczyk tomkiewicz at cpw.pidgin.im
Mon Mar 25 11:29:04 EDT 2013


Changeset: e9722a935271e2cf7e929ecffb418437eb710022
Author:	 Tomasz Wasilczyk <tomkiewicz at cpw.pidgin.im>
Date:	 2013-03-25 16:28 +0100
Branch:	 soc.2008.masterpassword
URL: https://hg.pidgin.im/cpw/tomkiewicz/masterpassword/rev/e9722a935271

Description:

Re-implemented GNOME Keyring plugin

diffstat:

 libpurple/keyring.c                       |   16 +-
 libpurple/plugins/keyrings/gnomekeyring.c |  322 ++++++++++++++++++++++++++++-
 libpurple/plugins/keyrings/kwallet.cpp    |   31 +-
 3 files changed, 337 insertions(+), 32 deletions(-)

diffs (truncated from 471 to 300 lines):

diff --git a/libpurple/keyring.c b/libpurple/keyring.c
--- a/libpurple/keyring.c
+++ b/libpurple/keyring.c
@@ -459,7 +459,7 @@ purple_keyring_set_inuse_check_error_cb(
 	}
 
 	/* if this was the last one */
-	if ((tracker->finished && tracker->read_outstanding == 0) || (tracker->abort && !tracker->force)) {
+	if (tracker->finished && tracker->read_outstanding == 0) {
 		if (tracker->abort && !tracker->force) {
 			purple_keyring_drop_passwords(tracker->new);
 
@@ -523,7 +523,11 @@ purple_keyring_set_inuse_got_pw_cb(Purpl
 	tracker = (PurpleKeyringChangeTracker *)data;
 	new = tracker->new;
 
-	g_return_if_fail(tracker->abort == FALSE);
+	g_return_if_fail(tracker != NULL);
+	if (tracker->abort) {
+		purple_keyring_set_inuse_check_error_cb(account, NULL, data);
+		return;
+	}
 
 	if (error != NULL) {
 		if (error->code == PURPLE_KEYRING_ERROR_NOPASSWD ||
@@ -638,9 +642,13 @@ purple_keyring_set_inuse(const PurpleKey
 			tracker->error = NULL;
 
 			for (cur = purple_accounts_get_all();
-			    (cur != NULL) && (tracker->abort == FALSE);
+			    cur != NULL;
 			    cur = cur->next) {
-
+				
+				if (tracker->abort) {
+					tracker->finished = TRUE;
+					break;
+				}
 				tracker->read_outstanding++;
 
 				if (cur->next == NULL)
diff --git a/libpurple/plugins/keyrings/gnomekeyring.c b/libpurple/plugins/keyrings/gnomekeyring.c
--- a/libpurple/plugins/keyrings/gnomekeyring.c
+++ b/libpurple/plugins/keyrings/gnomekeyring.c
@@ -32,33 +32,325 @@
 #include "version.h"
 
 #include <gnome-keyring.h>
+#include <gnome-keyring-memory.h>
 
 #define GNOMEKEYRING_NAME        N_("GNOME Keyring")
-#define GNOMEKEYRING_DESCRIPTION N_("This plugin will store passwords in GNOME Keyring.")
+#define GNOMEKEYRING_DESCRIPTION N_("This plugin will store passwords in " \
+	"GNOME Keyring.")
 #define GNOMEKEYRING_AUTHOR      "Tomek Wasilczyk (tomkiewicz at cpw.pidgin.im)"
 #define GNOMEKEYRING_ID          "keyring-gnomekeyring"
 
 static PurpleKeyring *keyring_handler = NULL;
+static GList *request_queue = NULL;
+static gpointer current_request = NULL;
+static gboolean is_closing = FALSE; /* TODO */
 
-static void
-keyring_gnome_read(PurpleAccount *account,PurpleKeyringReadCallback cb,
-	gpointer data)
+typedef struct
 {
+	enum
+	{
+		GNOMEKEYRING_REQUEST_READ,
+		GNOMEKEYRING_REQUEST_SAVE
+	} type;
+	PurpleAccount *account;
+	gchar *password;
+	union
+	{
+		PurpleKeyringReadCallback read;
+		PurpleKeyringSaveCallback save;
+	} cb;
+	gpointer cb_data;
+	gboolean handled;
+} gnomekeyring_request;
+
+static void gnomekeyring_cancel_queue(void);
+static void gnomekeyring_process_queue(void);
+
+static void gnomekeyring_request_free(gnomekeyring_request *req)
+{
+	if (req->password != NULL) {
+		memset(req->password, 0, strlen(req->password));
+		gnome_keyring_memory_free(req->password);
+	}
+	g_free(req);
 }
 
 static void
-keyring_gnome_save(PurpleAccount *account, const gchar *password,
-	PurpleKeyringSaveCallback cb, gpointer data)
+gnomekeyring_enqueue(gnomekeyring_request *req)
 {
+	request_queue = g_list_append(request_queue, req);
+	gnomekeyring_process_queue();
 }
 
 static void
-keyring_gnome_close(GError **error)
+gnomekeyring_read_cb(GnomeKeyringResult result, const char *password,
+	gpointer _req)
 {
+	gnomekeyring_request *req = _req;
+	PurpleAccount *account;
+	GError *error = NULL;
+
+	g_return_if_fail(req != NULL);
+
+	current_request = NULL;
+	account = req->account;
+
+	if (result == GNOME_KEYRING_RESULT_OK) {
+		error = NULL;
+	} else if (result == GNOME_KEYRING_RESULT_NO_MATCH) {
+		error = g_error_new(PURPLE_KEYRING_ERROR,
+			PURPLE_KEYRING_ERROR_NOPASSWD,
+			"No password found for account");
+	} else if (result == GNOME_KEYRING_RESULT_DENIED ||
+		result == GNOME_KEYRING_RESULT_CANCELLED) {
+		error = g_error_new(PURPLE_KEYRING_ERROR,
+			PURPLE_KEYRING_ERROR_WRONGPASS,
+			"Access denied");
+		gnomekeyring_cancel_queue();
+	} else if (result == GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON ||
+		GNOME_KEYRING_RESULT_IO_ERROR) {
+		error = g_error_new(PURPLE_KEYRING_ERROR,
+			PURPLE_KEYRING_ERROR_NOCHANNEL,
+			"Communication with GNOME Keyring failed");
+	} else {
+		error = g_error_new(PURPLE_KEYRING_ERROR,
+			PURPLE_KEYRING_ERROR_NOCHANNEL,
+			"Unknown error (code: %d)", result);
+	}
+
+	if (error == NULL && password == NULL) {
+		error = g_error_new(PURPLE_KEYRING_ERROR,
+			PURPLE_KEYRING_ERROR_NOCHANNEL,
+			"Unknown error (password empty)");
+	}
+
+	if (error == NULL) {
+		purple_debug_misc("keyring-gnome",
+			"Got password for account %s (%s).\n",
+			purple_account_get_username(account),
+			purple_account_get_protocol_id(account));
+	} else {
+		password = NULL;
+		purple_debug_warning("keyring-gnome", "Failed to read "
+			"password for account %s (%s), code: %d.\n",
+			purple_account_get_username(account),
+			purple_account_get_protocol_id(account),
+			result);
+	}
+
+	if (req->cb.read != NULL)
+		req->cb.read(account, password, error, req->cb_data);
+	req->handled = TRUE;
+
+	if (error)
+		g_error_free(error);
+
+	gnomekeyring_process_queue();
+}
+
+static void
+gnomekeyring_save_cb(GnomeKeyringResult result, gpointer _req)
+{
+	gnomekeyring_request *req = _req;
+	PurpleAccount *account;
+	GError *error = NULL;
+
+	g_return_if_fail(req != NULL);
+
+	current_request = NULL;
+	account = req->account;
+
+	if (result == GNOME_KEYRING_RESULT_OK) {
+		error = NULL;
+	} else if (result == GNOME_KEYRING_RESULT_DENIED ||
+		result == GNOME_KEYRING_RESULT_CANCELLED) {
+		error = g_error_new(PURPLE_KEYRING_ERROR,
+			PURPLE_KEYRING_ERROR_WRONGPASS,
+			"Access denied");
+		gnomekeyring_cancel_queue();
+	} else if (result == GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON ||
+		GNOME_KEYRING_RESULT_IO_ERROR) {
+		error = g_error_new(PURPLE_KEYRING_ERROR,
+			PURPLE_KEYRING_ERROR_NOCHANNEL,
+			"Communication with GNOME Keyring failed");
+	} else {
+		error = g_error_new(PURPLE_KEYRING_ERROR,
+			PURPLE_KEYRING_ERROR_NOCHANNEL,
+			"Unknown error (code: %d)", result);
+	}
+
+	if (error == NULL) {
+		purple_debug_misc("keyring-gnome",
+			"Password %s for account %s (%s).\n",
+			req->password ? "saved" : "removed",
+			purple_account_get_username(account),
+			purple_account_get_protocol_id(account));
+	} else {
+		purple_debug_warning("keyring-gnome", "Failed updating "
+			"password for account %s (%s), code: %d.\n",
+			purple_account_get_username(account),
+			purple_account_get_protocol_id(account),
+			result);
+	}
+
+	if (req->cb.save != NULL)
+		req->cb.save(account, error, req->cb_data);
+	req->handled = TRUE;
+
+	if (error)
+		g_error_free(error);
+
+	gnomekeyring_process_queue();
+}
+
+static void
+gnomekeyring_request_cancel(gpointer _req)
+{
+	gnomekeyring_request *req = _req;
+	PurpleAccount *account;
+	GError *error;
+
+	g_return_if_fail(req != NULL);
+
+	if (req->handled) {
+		gnomekeyring_request_free(req);
+		return;
+	}
+
+	purple_debug_warning("keyring-gnome",
+		"operation cancelled (%d %s:%s)\n", req->type,
+		purple_account_get_protocol_id(req->account),
+		purple_account_get_username(req->account));
+
+	account = req->account;
+	error = g_error_new(PURPLE_KEYRING_ERROR,
+		PURPLE_KEYRING_ERROR_NOCHANNEL,
+		"Operation cancelled");
+	if (req->type == GNOMEKEYRING_REQUEST_READ && req->cb.read)
+		req->cb.read(account, NULL, error, req->cb_data);
+	if (req->type == GNOMEKEYRING_REQUEST_SAVE && req->cb.save)
+		req->cb.save(account, error, req->cb_data);
+	g_error_free(error);
+
+	gnomekeyring_request_free(req);
+	gnomekeyring_process_queue();
+}
+
+static void
+gnomekeyring_cancel_queue(void)
+{
+	GList *cancel_list = request_queue;
+
+	purple_debug_info("gnome-keyring", "cancelling all pending requests\n");
+	request_queue = NULL;
+
+	g_list_free_full(cancel_list, gnomekeyring_request_cancel);
+}
+
+static void
+gnomekeyring_process_queue(void)
+{
+	gnomekeyring_request *req;
+	PurpleAccount *account;
+	GList *first;
+
+	if (request_queue == NULL)
+		return;
+
+	if (current_request) {
+		if (purple_debug_is_verbose())
+			purple_debug_misc("keyring-gnome", "busy...\n");
+		return;
+	}
+
+	first = g_list_first(request_queue);
+	req = first->data;
+	request_queue = g_list_delete_link(request_queue, first);
+	account = req->account;
+
+	if (purple_debug_is_verbose()) {
+		purple_debug_misc("keyring-gnome",
+			"%s password for account %s (%s)\n",
+			req->type == GNOMEKEYRING_REQUEST_READ ? "reading" :
+			(req->password == NULL ? "removing" : "updating"),
+			purple_account_get_username(account),
+			purple_account_get_protocol_id(account));
+	}
+



More information about the Commits mailing list