/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