/cpw/tomkiewicz/masterpassword: 9d90967f2485: Don't close a keyr...

Tomasz Wasilczyk tomkiewicz at cpw.pidgin.im
Tue Mar 26 10:55:36 EDT 2013


Changeset: 9d90967f24858eca38223cc862508a34bf54e354
Author:	 Tomasz Wasilczyk <tomkiewicz at cpw.pidgin.im>
Date:	 2013-03-26 15:55 +0100
Branch:	 soc.2008.masterpassword
URL: https://hg.pidgin.im/cpw/tomkiewicz/masterpassword/rev/9d90967f2485

Description:

Don't close a keyring before dropping all passwords

diffstat:

 libpurple/keyring.c                       |  156 ++++++++++++++++++++---------
 libpurple/plugins/keyrings/gnomekeyring.c |   16 ++-
 2 files changed, 120 insertions(+), 52 deletions(-)

diffs (270 lines):

diff --git a/libpurple/keyring.c b/libpurple/keyring.c
--- a/libpurple/keyring.c
+++ b/libpurple/keyring.c
@@ -68,6 +68,7 @@ struct _PurpleKeyringChangeTracker
 	gboolean finished;
 	gboolean abort;
 	gboolean force;
+	gboolean succeeded;
 };
 
 struct _PurpleKeyringCbInfo
@@ -76,6 +77,16 @@ struct _PurpleKeyringCbInfo
 	gpointer data;
 };
 
+typedef void (*PurpleKeyringDropCallback)(gpointer data);
+
+typedef struct
+{
+	PurpleKeyringDropCallback cb;
+	gpointer cb_data;
+	int drop_outstanding;
+	gboolean finished;
+} PurpleKeyringDropTracker;
+
 static void
 purple_keyring_change_tracker_free(PurpleKeyringChangeTracker *tracker)
 {
@@ -452,21 +463,95 @@ purple_keyring_get_inuse(void)
 }
 
 
-/* fire and forget */
 static void
-purple_keyring_drop_passwords(const PurpleKeyring *keyring)
+purple_keyring_drop_passwords_cb(PurpleAccount *account, GError *error,
+	gpointer _tracker)
+{
+	PurpleKeyringDropTracker *tracker = _tracker;
+
+	tracker->drop_outstanding--;
+
+	if (!tracker->finished || tracker->drop_outstanding > 0)
+		return;
+
+	if (tracker->cb)
+		tracker->cb(tracker->cb_data);
+	g_free(tracker);
+}
+
+static void
+purple_keyring_drop_passwords(const PurpleKeyring *keyring,
+	PurpleKeyringDropCallback cb, gpointer data)
 {
 	GList *cur;
 	PurpleKeyringSave save;
+	PurpleKeyringDropTracker *tracker;
+
+	g_return_if_fail(keyring != NULL);
 
 	save = purple_keyring_get_save_password(keyring);
+	if (save == NULL) {
+		if (cb)
+			cb(data);
+		return;
+	}
 
-	g_return_if_fail(save != NULL);
+	tracker = g_new0(PurpleKeyringDropTracker, 1);
+	tracker->cb = cb;
+	tracker->cb_data = data;
 
-	for (cur = purple_accounts_get_all();
-	     cur != NULL;
-	     cur = cur->next)
-		save(cur->data, NULL, NULL, NULL);
+	for (cur = purple_accounts_get_all(); cur != NULL; cur = cur->next) {
+		tracker->drop_outstanding++;
+		if (cur->next == NULL)
+			tracker->finished = TRUE;
+
+		save(cur->data, NULL, purple_keyring_drop_passwords_cb,
+			tracker);
+	}
+}
+
+static void
+purple_keyring_set_inuse_drop_cb(gpointer _tracker)
+{
+	PurpleKeyringChangeTracker *tracker = _tracker;
+
+	g_return_if_fail(tracker != NULL);
+
+	if (tracker->succeeded) {
+		PurpleKeyringClose close =
+			purple_keyring_get_close_keyring(tracker->old);
+		if (close != NULL)
+			close(NULL);
+
+		purple_debug_info("keyring", "Successfully changed keyring.\n");
+
+		purple_keyring_inuse = tracker->new;
+		current_change_tracker = NULL;
+
+		if (tracker->cb != NULL)
+			tracker->cb(tracker->new, TRUE, NULL, tracker->data);
+	} else {
+		PurpleKeyringClose close =
+			purple_keyring_get_close_keyring(tracker->new);
+		if (close != NULL)
+			close(NULL);
+
+		purple_debug_error("keyring",
+			"Failed to change keyring, aborting.\n");
+
+		purple_prefs_disconnect_callback(purple_keyring_pref_cb_id);
+		purple_prefs_set_string("/purple/keyring/active",
+			purple_keyring_get_id(tracker->old));
+		purple_keyring_pref_cb_id = purple_prefs_connect_callback(NULL,
+			"/purple/keyring/active", purple_keyring_pref_cb, NULL);
+
+		current_change_tracker = NULL;
+
+		if (tracker->cb != NULL)
+			tracker->cb(tracker->old, FALSE, tracker->error, tracker->data);
+	}
+
+	purple_keyring_change_tracker_free(tracker);
 }
 
 static void
@@ -475,7 +560,6 @@ purple_keyring_set_inuse_check_error_cb(
 					gpointer data)
 {
 	const char *name;
-	PurpleKeyringClose close;
 	PurpleKeyringChangeTracker *tracker;
 
 	tracker = (PurpleKeyringChangeTracker *)data;
@@ -521,47 +605,6 @@ purple_keyring_set_inuse_check_error_cb(
 		}
 	}
 
-	/* if this was the last one */
-	if (tracker->finished && tracker->read_outstanding == 0) {
-		if (tracker->abort && !tracker->force) {
-			purple_keyring_drop_passwords(tracker->new);
-
-			close = purple_keyring_get_close_keyring(tracker->new);
-			if (close != NULL)
-				close(NULL);
-
-			purple_debug_error("keyring",
-				"Failed to change keyring, aborting.\n");
-
-			purple_prefs_disconnect_callback(purple_keyring_pref_cb_id);
-			purple_prefs_set_string("/purple/keyring/active",
-				purple_keyring_get_id(tracker->old));
-			purple_keyring_pref_cb_id = purple_prefs_connect_callback(NULL,
-				"/purple/keyring/active", purple_keyring_pref_cb, NULL);
-
-			current_change_tracker = NULL;
-
-			if (tracker->cb != NULL)
-				tracker->cb(tracker->old, FALSE, tracker->error, tracker->data);
-		} else {
-			purple_keyring_drop_passwords(tracker->old);
-
-			close = purple_keyring_get_close_keyring(tracker->old);
-			if (close != NULL)
-				close(&error);
-
-			purple_debug_info("keyring", "Successfully changed keyring.\n");
-
-			purple_keyring_inuse = tracker->new;
-			current_change_tracker = NULL;
-
-			if (tracker->cb != NULL)
-				tracker->cb(tracker->new, TRUE, NULL, tracker->data);
-		}
-
-		purple_keyring_change_tracker_free(tracker);
-	}
-
 	/**
 	 * This is kind of hackish. It will schedule an account save.
 	 *
@@ -571,6 +614,17 @@ purple_keyring_set_inuse_check_error_cb(
 	 */
 	purple_account_set_remember_password(account,
 		purple_account_get_remember_password(account));
+
+	/* if this was the last one */
+	if (tracker->finished && tracker->read_outstanding == 0) {
+		if (tracker->abort && !tracker->force) {
+			tracker->succeeded = FALSE;
+			purple_keyring_drop_passwords(tracker->new, purple_keyring_set_inuse_drop_cb, tracker);
+		} else {
+			tracker->succeeded = TRUE;
+			purple_keyring_drop_passwords(tracker->old, purple_keyring_set_inuse_drop_cb, tracker);
+		}
+	}
 }
 
 static void
@@ -665,7 +719,7 @@ purple_keyring_set_inuse(const PurpleKey
 	if (oldkeyring != NULL) {
 		read = purple_keyring_get_read_password(oldkeyring);
 
-		if (read == NULL) {
+		if (read == NULL) { /* TODO: don't allow registering a keyring without read/save callback */
 			/*
 			error = g_error_new(PURPLE_KEYRING_ERROR, PURPLE_KEYRING_ERROR_NOCAP,
 				"Existing keyring cannot read passwords");
@@ -678,7 +732,7 @@ purple_keyring_set_inuse(const PurpleKey
 			 * one later.
 			 */
 
-			purple_keyring_drop_passwords(oldkeyring);
+			purple_keyring_drop_passwords(oldkeyring, NULL, NULL);
 
 			close = purple_keyring_get_close_keyring(oldkeyring);
 
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
@@ -128,6 +128,13 @@ gnomekeyring_read_cb(GnomeKeyringResult 
 			"Got password for account %s (%s).\n",
 			purple_account_get_username(account),
 			purple_account_get_protocol_id(account));
+	} else if (result == GNOME_KEYRING_RESULT_NO_MATCH) {
+		if (purple_debug_is_verbose()) {
+			purple_debug_info("keyring-gnome",
+				"Password for account %s (%s) isn't stored.\n",
+				purple_account_get_username(account),
+				purple_account_get_protocol_id(account));
+		}
 	} else {
 		password = NULL;
 		purple_debug_warning("keyring-gnome", "Failed to read "
@@ -153,6 +160,7 @@ gnomekeyring_save_cb(GnomeKeyringResult 
 	gnomekeyring_request *req = _req;
 	PurpleAccount *account;
 	GError *error = NULL;
+	gboolean already_removed = FALSE;
 
 	g_return_if_fail(req != NULL);
 
@@ -161,6 +169,10 @@ gnomekeyring_save_cb(GnomeKeyringResult 
 
 	if (result == GNOME_KEYRING_RESULT_OK) {
 		error = NULL;
+	} else if (result == GNOME_KEYRING_RESULT_NO_MATCH &&
+		req->password == NULL) {
+		error = NULL;
+		already_removed = TRUE;
 	} else if (result == GNOME_KEYRING_RESULT_DENIED ||
 		result == GNOME_KEYRING_RESULT_CANCELLED) {
 		error = g_error_new(PURPLE_KEYRING_ERROR,
@@ -178,7 +190,9 @@ gnomekeyring_save_cb(GnomeKeyringResult 
 			"Unknown error (code: %d)", result);
 	}
 
-	if (error == NULL) {
+	if (already_removed) {
+		/* no operation */
+	} else if (error == NULL) {
 		purple_debug_misc("keyring-gnome",
 			"Password %s for account %s (%s).\n",
 			req->password ? "saved" : "removed",



More information about the Commits mailing list