/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