aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--e-util/ChangeLog12
-rw-r--r--e-util/e-passwords.c732
-rw-r--r--e-util/e-passwords.h30
3 files changed, 560 insertions, 214 deletions
diff --git a/e-util/ChangeLog b/e-util/ChangeLog
index 8f082be051..cae9acbc05 100644
--- a/e-util/ChangeLog
+++ b/e-util/ChangeLog
@@ -1,3 +1,15 @@
+2004-08-10 Not Zed <NotZed@Ximian.com>
+
+ ** See bug #61840, and others.
+
+ * e-passwords.c: Lots of changes. The api is now fully
+ multi-thread safe, all calls are serialised internally, even
+ recursive main-loop calls. Small api changes to the
+ ask_password call to add some new features required by the mailer
+ and to clean up some of the names.
+ (e_passwords_cancel): new procedure to cancel any outstanding
+ password requests, for when we need to go uninteractive.
+
2004-08-09 Rodney Dawes <dobey@novell.com>
* e-icon-factory.c (icon_foreach_remove): We must return TRUE here
diff --git a/e-util/e-passwords.c b/e-util/e-passwords.c
index 11a69a3276..61627729dd 100644
--- a/e-util/e-passwords.c
+++ b/e-util/e-passwords.c
@@ -22,40 +22,182 @@
* USA.
*/
+/*
+ * This looks a lot more complicated than it is, and than you'd think
+ * it would need to be. There is however, method to the madness.
+ *
+ * The code most cope with being called from any thread at any time,
+ * recursively from the main thread, and then serialising every
+ * request so that sane and correct values are always returned, and
+ * duplicate requests are never made.
+ *
+ * To this end, every call is marshalled and queued and a dispatch
+ * method invoked until that request is satisfied. If mainloop
+ * recursion occurs, then the sub-call will necessarily return out of
+ * order, but will not be processed out of order.
+ */
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#include "e-passwords.h"
#include <string.h>
#include <libgnome/gnome-config.h>
#include <libgnome/gnome-i18n.h>
#include <gtk/gtkentry.h>
-#include <gtk/gtkbox.h>
+#include <gtk/gtkvbox.h>
#include <gtk/gtkcheckbutton.h>
#include <gtk/gtkmessagedialog.h>
-static char *decode_base64 (char *base64);
+#include "e-passwords.h"
+#include "e-msgport.h"
+#include "widgets/misc/e-error.h"
+
+#ifndef ENABLE_THREADS
+#define ENABLE_THREADS (1)
+#endif
+
+#ifdef ENABLE_THREADS
+#include <pthread.h>
+
+static pthread_t main_thread;
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+#define LOCK() pthread_mutex_lock(&lock)
+#define UNLOCK() pthread_mutex_unlock(&lock)
+#else
+#define LOCK()
+#define UNLOCK()
+#endif
+
+struct _EPassMsg {
+ EMsg msg;
+
+ void (*dispatch)(struct _EPassMsg *);
+
+ /* input */
+ struct _GtkWindow *parent;
+ const char *component;
+ const char *key;
+ const char *title;
+ const char *prompt;
+ const char *oldpass;
+ guint32 flags;
+
+ /* output */
+ gboolean *remember;
+ char *password;
+
+ /* work variables */
+ GtkWidget *entry;
+ GtkWidget *check;
+ int ismain:1;
+ int noreply:1; /* supress replies; when calling
+ * dispatch functions from others */
+};
+
+typedef struct _EPassMsg EPassMsg;
static GHashTable *passwords = NULL;
+static GtkDialog *password_dialog;
+static EDList request_list = E_DLIST_INITIALISER(request_list);
+static int idle_id;
+static char *decode_base64 (char *base64);
static int base64_encode_close(unsigned char *in, int inlen, gboolean break_lines, unsigned char *out, int *state, int *save);
static int base64_encode_step(unsigned char *in, int len, gboolean break_lines, unsigned char *out, int *state, int *save);
-/**
- * e_passwords_init:
- *
- * Initializes the e_passwords routines. Must be called before any other
- * e_passwords_* function.
- **/
+static gboolean
+ep_idle_dispatch(void *data)
+{
+ EPassMsg *msg;
+
+ /* As soon as a password window is up we stop; it will
+ re-invoke us when it has been closed down */
+ LOCK();
+ while (password_dialog == NULL && (msg = (EPassMsg *)e_dlist_remhead(&request_list))) {
+ UNLOCK();
+
+ msg->dispatch(msg);
+
+ LOCK();
+ }
+
+ idle_id = 0;
+ UNLOCK();
+
+ return FALSE;
+}
+
+static EPassMsg *
+ep_msg_new(void (*dispatch)(EPassMsg *))
+{
+ EPassMsg *msg;
+
+ e_passwords_init();
+
+ msg = g_malloc0(sizeof(*msg));
+ msg->dispatch = dispatch;
+ msg->msg.reply_port = e_msgport_new();
+#ifdef ENABLE_THREADS
+ msg->ismain = pthread_self() == main_thread;
+#else
+ msg->ismain = TRUE;
+#endif
+ return msg;
+}
+
+static void
+ep_msg_free(EPassMsg *msg)
+{
+ e_msgport_destroy(msg->msg.reply_port);
+ g_free(msg->password);
+ g_free(msg);
+}
+
static void
-e_passwords_init ()
+ep_msg_send(EPassMsg *msg)
{
- if (passwords)
- return;
+ int needidle = 0;
- /* create the per-session hash table */
- passwords = g_hash_table_new (g_str_hash, g_str_equal);
+ LOCK();
+ e_dlist_addtail(&request_list, (EDListNode *)&msg->msg);
+ if (!idle_id) {
+ if (!msg->ismain)
+ idle_id = g_idle_add(ep_idle_dispatch, NULL);
+ else
+ needidle = 1;
+ }
+ UNLOCK();
+
+ if (msg->ismain) {
+ EPassMsg *m;
+
+ if (needidle)
+ ep_idle_dispatch(NULL);
+ while ((m = (EPassMsg *)e_msgport_get(msg->msg.reply_port)) == NULL)
+ g_main_context_iteration(NULL, TRUE);
+ g_assert(m == msg);
+ } else {
+ e_msgport_wait(msg->msg.reply_port);
+ g_assert(e_msgport_get(msg->msg.reply_port) == &msg->msg);
+ }
+}
+
+/* the functions that actually do the work */
+static void
+ep_clear_passwords(EPassMsg *msg)
+{
+ char *path;
+
+ path = g_strdup_printf ("/Evolution/Passwords-%s", msg->component);
+
+ gnome_config_private_clean_section (path);
+ gnome_config_private_sync_file ("/Evolution");
+
+ g_free (path);
+
+ if (!msg->noreply)
+ e_msgport_reply(&msg->msg);
}
static gboolean
@@ -67,39 +209,12 @@ free_entry (gpointer key, gpointer value, gpointer user_data)
return TRUE;
}
-/**
- * e_passwords_shutdown:
- *
- * Cleanup routine to call before exiting.
- **/
-void
-e_passwords_shutdown ()
-{
- /* shouldn't need this really - everything is synchronous */
- gnome_config_private_sync_file ("/Evolution");
-
- if (passwords) {
- /* and destroy our per session hash */
- g_hash_table_foreach_remove (passwords, free_entry, NULL);
- g_hash_table_destroy (passwords);
- passwords = NULL;
- }
-}
-
-
-/**
- * e_passwords_forget_passwords:
- *
- * Forgets all cached passwords, in memory and on disk.
- **/
-void
-e_passwords_forget_passwords ()
+static void
+ep_forget_passwords(EPassMsg *msg)
{
void *it;
char *key;
- e_passwords_init ();
-
it = gnome_config_private_init_iterator_sections("/Evolution");
while ( (it = gnome_config_iterator_next(it, &key, NULL)) ) {
if (0 == strncmp(key, "Passwords-", 10)) {
@@ -111,31 +226,13 @@ e_passwords_forget_passwords ()
g_free(key);
}
- /*gnome_config_private_clean_section ("/Evolution/Passwords-Mail");*/
gnome_config_private_sync_file ("/Evolution");
/* free up the session passwords */
g_hash_table_foreach_remove (passwords, free_entry, NULL);
-}
-
-/**
- * e_passwords_clear_component_passwords:
- *
- * Forgets all disk cached passwords.
- **/
-void
-e_passwords_clear_component_passwords (const char *component_name)
-{
- char *path;
-
- e_passwords_init ();
- path = g_strdup_printf ("/Evolution/Passwords-%s", component_name);
-
- gnome_config_private_clean_section (path);
- gnome_config_private_sync_file ("/Evolution");
-
- g_free (path);
+ if (!msg->noreply)
+ e_msgport_reply(&msg->msg);
}
static char *
@@ -156,42 +253,337 @@ password_path (const char *component_name, const char *key)
return path;
}
-/**
- * e_passwords_remember_password:
- * @key: the key
- *
- * Saves the password associated with @key to disk.
- **/
-void
-e_passwords_remember_password (const char *component_name, const char *key)
+static void
+ep_remember_password(EPassMsg *msg)
{
gpointer okey, value;
char *path, *pass64;
int len, state, save;
- e_passwords_init ();
+ if (g_hash_table_lookup_extended (passwords, msg->key, &okey, &value)) {
+ /* add it to the on-disk cache of passwords */
+ path = password_path (msg->component, okey);
- if (!g_hash_table_lookup_extended (passwords, key, &okey, &value))
- return;
+ len = strlen (value);
+ pass64 = g_malloc0 ((len + 2) * 4 / 3 + 1);
+ state = save = 0;
+ base64_encode_close (value, len, FALSE, pass64, &state, &save);
- /* add it to the on-disk cache of passwords */
- path = password_path (component_name, okey);
+ gnome_config_private_set_string (path, pass64);
+ g_free (path);
+ g_free (pass64);
- len = strlen (value);
- pass64 = g_malloc0 ((len + 2) * 4 / 3 + 1);
- state = save = 0;
- base64_encode_close (value, len, FALSE, pass64, &state, &save);
+ /* now remove it from our session hash */
+ g_hash_table_remove (passwords, msg->key);
+ g_free (okey);
+ g_free (value);
+
+ gnome_config_private_sync_file ("/Evolution");
+ }
- gnome_config_private_set_string (path, pass64);
+ if (!msg->noreply)
+ e_msgport_reply(&msg->msg);
+}
+
+static void
+ep_forget_password (EPassMsg *msg)
+{
+ gpointer okey, value;
+ char *path;
+
+ if (g_hash_table_lookup_extended (passwords, msg->key, &okey, &value)) {
+ g_hash_table_remove (passwords, msg->key);
+ memset (value, 0, strlen (value));
+ g_free (okey);
+ g_free (value);
+ }
+
+ /* clear it in the on disk db */
+ path = password_path (msg->component, msg->key);
+ gnome_config_private_clean_key (path);
+ gnome_config_private_sync_file ("/Evolution");
g_free (path);
- g_free (pass64);
+
+ if (!msg->noreply)
+ e_msgport_reply(&msg->msg);
+}
- /* now remove it from our session hash */
- g_hash_table_remove (passwords, key);
- g_free (okey);
- g_free (value);
+static void
+ep_get_password (EPassMsg *msg)
+{
+ char *path, *passwd;
+ char *encoded = NULL;
+
+ passwd = g_hash_table_lookup (passwords, msg->key);
+ if (passwd) {
+ msg->password = g_strdup(passwd);
+ } else {
+ /* not part of the session hash, look it up in the on disk db */
+ path = password_path (msg->component, msg->key);
+ encoded = gnome_config_private_get_string_with_default (path, NULL);
+ g_free (path);
+ if (encoded) {
+ msg->password = decode_base64 (encoded);
+ g_free (encoded);
+ }
+ }
+
+ if (!msg->noreply)
+ e_msgport_reply(&msg->msg);
+}
+
+static void
+ep_add_password (EPassMsg *msg)
+{
+ gpointer okey, value;
+
+ if (g_hash_table_lookup_extended (passwords, msg->key, &okey, &value)) {
+ g_hash_table_remove (passwords, msg->key);
+ g_free (okey);
+ g_free (value);
+ }
+
+ g_hash_table_insert (passwords, g_strdup (msg->key), g_strdup (msg->oldpass));
+
+ if (!msg->noreply)
+ e_msgport_reply(&msg->msg);
+}
+
+static void ep_ask_password(EPassMsg *msg);
+static void
+pass_response(GtkDialog *dialog, int response, void *data)
+{
+ EPassMsg *msg = data;
+ int type = msg->flags & E_PASSWORDS_REMEMBER_MASK;
+ EDList pending = E_DLIST_INITIALISER(pending);
+ EPassMsg *mw, *mn;
+
+ if (response == GTK_RESPONSE_OK) {
+ msg->password = g_strdup(gtk_entry_get_text((GtkEntry *)msg->entry));
+
+ if (type != E_PASSWORDS_REMEMBER_NEVER) {
+ int noreply = msg->noreply;
+
+ *msg->remember = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (msg->check));
+
+ msg->noreply = 1;
+
+ if (*msg->remember || type == E_PASSWORDS_REMEMBER_FOREVER) {
+ msg->oldpass = msg->password;
+ ep_add_password(msg);
+ }
+
+ if (*msg->remember && type == E_PASSWORDS_REMEMBER_FOREVER)
+ ep_remember_password(msg);
+
+ msg->noreply = noreply;
+ }
+ }
+
+ gtk_widget_destroy((GtkWidget *)dialog);
+ password_dialog = NULL;
+
+ /* ok, here things get interesting, we suck up any pending
+ * operations on this specific password, and return the same
+ * result or ignore other operations */
+
+ LOCK();
+ mw = (EPassMsg *)request_list.head;
+ mn = (EPassMsg *)mw->msg.ln.next;
+ while (mn) {
+ if ((mw->dispatch == ep_forget_password
+ || mw->dispatch == ep_get_password
+ || mw->dispatch == ep_ask_password)
+ && (strcmp(mw->component, msg->component) == 0
+ && strcmp(mw->key, msg->key) == 0)) {
+ e_dlist_remove((EDListNode *)mw);
+ mw->password = g_strdup(msg->password);
+ e_msgport_reply(&mw->msg);
+ }
+ mw = mn;
+ mn = (EPassMsg *)mn->msg.ln.next;
+ }
+ UNLOCK();
+
+ if (!msg->noreply)
+ e_msgport_reply(&msg->msg);
+
+ ep_idle_dispatch(NULL);
+}
+
+static void
+ep_ask_password(EPassMsg *msg)
+{
+ GtkWidget *vbox;
+ int type = msg->flags & E_PASSWORDS_REMEMBER_MASK;
+ int noreply = msg->noreply;
+
+ msg->noreply = 1;
+
+ /*password_dialog = (GtkDialog *)e_error_new(msg->parent, "mail:ask-session-password", msg->prompt, NULL);*/
+ password_dialog = (GtkDialog *)gtk_message_dialog_new (msg->parent,
+ 0,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_OK_CANCEL,
+ msg->prompt);
+ gtk_window_set_title(GTK_WINDOW(password_dialog), msg->title);
+
+ gtk_dialog_set_has_separator(password_dialog, FALSE);
+ gtk_dialog_set_default_response(password_dialog, GTK_RESPONSE_OK);
+
+ vbox = gtk_vbox_new (FALSE, 6);
+ gtk_widget_show (vbox);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (password_dialog)->vbox), vbox, TRUE, FALSE, 0);
+ gtk_container_set_border_width((GtkContainer *)vbox, 6);
+
+ msg->entry = gtk_entry_new ();
+ gtk_entry_set_visibility ((GtkEntry *)msg->entry, !(msg->flags & E_PASSWORDS_SECRET));
+ gtk_entry_set_activates_default((GtkEntry *)msg->entry, TRUE);
+ gtk_box_pack_start (GTK_BOX (vbox), msg->entry, TRUE, FALSE, 3);
+ gtk_widget_show (msg->entry);
+ gtk_widget_grab_focus (msg->entry);
+
+ if ((msg->flags & E_PASSWORDS_REPROMPT)) {
+ ep_get_password(msg);
+ if (msg->password) {
+ gtk_entry_set_text ((GtkEntry *) msg->entry, msg->password);
+ g_free (msg->password);
+ msg->password = NULL;
+ }
+ }
+
+ /* static password, shouldn't be remembered between sessions,
+ but will be remembered within the session beyond our control */
+ if (type != E_PASSWORDS_REMEMBER_NEVER) {
+ msg->check = gtk_check_button_new_with_mnemonic(type == E_PASSWORDS_REMEMBER_FOREVER
+ ? _("_Remember this password")
+ : _("_Remember this password for the remainder of this session"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (msg->check), *msg->remember);
+ gtk_box_pack_start (GTK_BOX (vbox), msg->check, TRUE, FALSE, 3);
+ gtk_widget_show (msg->check);
+ }
+
+ msg->noreply = noreply;
+
+ g_signal_connect(password_dialog, "response", G_CALLBACK (pass_response), msg);
+ gtk_widget_show((GtkWidget *)password_dialog);
+}
+
+
+/**
+ * e_passwords_init:
+ *
+ * Initializes the e_passwords routines. Must be called before any other
+ * e_passwords_* function.
+ **/
+void
+e_passwords_init (void)
+{
+ LOCK();
+
+ if (!passwords) {
+ /* create the per-session hash table */
+ passwords = g_hash_table_new (g_str_hash, g_str_equal);
+#ifdef ENABLE_THREADS
+ main_thread = pthread_self();
+#endif
+ }
+
+ UNLOCK();
+}
+
+/**
+ * e_passwords_cancel:
+ *
+ * Cancel any outstanding password operations and close any dialogues
+ * currently being shown.
+ **/
+void
+e_passwords_cancel(void)
+{
+ EPassMsg *msg;
+
+ LOCK();
+ while ((msg = (EPassMsg *)e_dlist_remhead(&request_list)))
+ e_msgport_reply(&msg->msg);
+ UNLOCK();
+
+ if (password_dialog)
+ gtk_widget_destroy((GtkWidget *)password_dialog);
+}
+
+/**
+ * e_passwords_shutdown:
+ *
+ * Cleanup routine to call before exiting.
+ **/
+void
+e_passwords_shutdown (void)
+{
+ /* shouldn't need this really - everything is synchronous */
gnome_config_private_sync_file ("/Evolution");
+
+ e_passwords_cancel();
+
+ if (passwords) {
+ /* and destroy our per session hash */
+ g_hash_table_foreach_remove (passwords, free_entry, NULL);
+ g_hash_table_destroy (passwords);
+ passwords = NULL;
+ }
+}
+
+/**
+ * e_passwords_forget_passwords:
+ *
+ * Forgets all cached passwords, in memory and on disk.
+ **/
+void
+e_passwords_forget_passwords (void)
+{
+ EPassMsg *msg = ep_msg_new(ep_forget_passwords);
+
+ ep_msg_send(msg);
+ ep_msg_free(msg);
+}
+
+/**
+ * e_passwords_clear_passwords:
+ *
+ * Forgets all disk cached passwords for the component.
+ **/
+void
+e_passwords_clear_passwords (const char *component_name)
+{
+ EPassMsg *msg = ep_msg_new(ep_clear_passwords);
+
+ msg->component = component_name;
+ ep_msg_send(msg);
+ ep_msg_free(msg);
+}
+
+/**
+ * e_passwords_remember_password:
+ * @key: the key
+ *
+ * Saves the password associated with @key to disk.
+ **/
+void
+e_passwords_remember_password (const char *component_name, const char *key)
+{
+ EPassMsg *msg;
+
+ g_return_if_fail(component_name != NULL);
+ g_return_if_fail(key != NULL);
+
+ msg = ep_msg_new(ep_remember_password);
+
+ msg->component = component_name;
+ msg->key = key;
+
+ ep_msg_send(msg);
+ ep_msg_free(msg);
}
/**
@@ -203,23 +595,18 @@ e_passwords_remember_password (const char *component_name, const char *key)
void
e_passwords_forget_password (const char *component_name, const char *key)
{
- gpointer okey, value;
- char *path;
+ EPassMsg *msg;
- e_passwords_init ();
+ g_return_if_fail(component_name != NULL);
+ g_return_if_fail(key != NULL);
- if (g_hash_table_lookup_extended (passwords, key, &okey, &value)) {
- g_hash_table_remove (passwords, key);
- memset (value, 0, strlen (value));
- g_free (okey);
- g_free (value);
- }
+ msg = ep_msg_new(ep_forget_password);
- /* clear it in the on disk db */
- path = password_path (component_name, key);
- gnome_config_private_clean_key (path);
- gnome_config_private_sync_file ("/Evolution");
- g_free (path);
+ msg->component = component_name;
+ msg->key = key;
+
+ ep_msg_send(msg);
+ ep_msg_free(msg);
}
/**
@@ -232,28 +619,23 @@ e_passwords_forget_password (const char *component_name, const char *key)
char *
e_passwords_get_password (const char *component_name, const char *key)
{
- char *path, *passwd;
- char *encoded = NULL;
+ EPassMsg *msg;
+ char *passwd;
- e_passwords_init ();
-
- passwd = g_hash_table_lookup (passwords, key);
- if (passwd)
- return g_strdup (passwd);
-
- /* not part of the session hash, look it up in the on disk db */
- path = password_path (component_name, key);
+ g_return_val_if_fail(component_name != NULL, NULL);
+ g_return_val_if_fail(key != NULL, NULL);
- encoded = gnome_config_private_get_string_with_default (path, NULL);
-
- g_free (path);
+ msg = ep_msg_new(ep_get_password);
+
+ msg->component = component_name;
+ msg->key = key;
+
+ ep_msg_send(msg);
+
+ passwd = msg->password;
+ msg->password = NULL;
+ ep_msg_free(msg);
- if (!encoded)
- return NULL;
-
- passwd = decode_base64 (encoded);
- g_free (encoded);
-
return passwd;
}
@@ -268,28 +650,17 @@ e_passwords_get_password (const char *component_name, const char *key)
void
e_passwords_add_password (const char *key, const char *passwd)
{
- gpointer okey, value;
-
- e_passwords_init ();
-
- /* FIXME: shouldn't this be g_return_if_fail? */
- if (!key || !passwd)
- return;
-
- if (g_hash_table_lookup_extended (passwords, key, &okey, &value)) {
- g_hash_table_remove (passwords, key);
- g_free (okey);
- g_free (value);
- }
+ EPassMsg *msg;
- g_hash_table_insert (passwords, g_strdup (key), g_strdup (passwd));
-}
+ g_return_if_fail(key != NULL);
+ g_return_if_fail(passwd != NULL);
+ msg = ep_msg_new(ep_add_password);
+ msg->key = key;
+ msg->oldpass = passwd;
-static void
-entry_activate (GtkEntry *entry, GtkDialog *dialog)
-{
- gtk_dialog_response (dialog, GTK_RESPONSE_OK);
+ ep_msg_send(msg);
+ ep_msg_free(msg);
}
/**
@@ -316,75 +687,28 @@ entry_activate (GtkEntry *entry, GtkDialog *dialog)
char *
e_passwords_ask_password (const char *title, const char *component_name,
const char *key,
- const char *prompt, gboolean secret,
- EPasswordsRememberType remember_type,
+ const char *prompt,
+ EPasswordsRememberType type,
gboolean *remember,
GtkWindow *parent)
{
- GtkWidget *dialog;
- GtkWidget *check = NULL, *entry;
- char *password;
- int response;
-
- dialog = gtk_message_dialog_new (parent,
- 0,
- GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_OK_CANCEL,
- prompt);
-
- gtk_window_set_title (GTK_WINDOW (dialog), title);
-
- gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
- gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-
- /* Password entry */
- entry = gtk_entry_new();
- if (secret)
- gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
-
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
- entry, FALSE, FALSE, 4);
- gtk_widget_show (entry);
- gtk_widget_grab_focus (entry);
-
- g_signal_connect (entry, "activate",
- G_CALLBACK (entry_activate), dialog);
-
- /* Remember the password? */
- if (remember_type != E_PASSWORDS_DO_NOT_REMEMBER) {
- const char *label;
-
- if (remember_type == E_PASSWORDS_REMEMBER_FOREVER)
- label = _("Remember this password");
- else
- label = _("Remember this password for the remainder of this session");
- check = gtk_check_button_new_with_label (label);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check),
- *remember);
-
- gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->vbox),
- check, TRUE, FALSE, 4);
- gtk_widget_show (check);
- }
-
- response = gtk_dialog_run (GTK_DIALOG (dialog));
-
- if (response == GTK_RESPONSE_OK) {
- password = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
- if (remember_type != E_PASSWORDS_DO_NOT_REMEMBER) {
- *remember = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check));
-
- if (*remember || remember_type == E_PASSWORDS_REMEMBER_FOREVER)
- e_passwords_add_password (key, password);
- if (*remember && remember_type == E_PASSWORDS_REMEMBER_FOREVER)
- e_passwords_remember_password (component_name, key);
- }
- } else
- password = NULL;
-
- gtk_widget_destroy (dialog);
-
- return password;
+ char *passwd;
+ EPassMsg *msg = ep_msg_new(ep_ask_password);
+
+ msg->title = title;
+ msg->component = component_name;
+ msg->key = key;
+ msg->prompt = prompt;
+ msg->flags = type;
+ msg->remember = remember;
+ msg->parent = parent;
+
+ ep_msg_send(msg);
+ passwd = msg->password;
+ msg->password = NULL;
+ ep_msg_free(msg);
+
+ return passwd;
}
diff --git a/e-util/e-passwords.h b/e-util/e-passwords.h
index 7a2b2aa17f..d68cf6aa6c 100644
--- a/e-util/e-passwords.h
+++ b/e-util/e-passwords.h
@@ -28,28 +28,38 @@
G_BEGIN_DECLS
-/* initialization is now implicit when you call any of the functions
- below (except _shutdown.). e_passwords_shutdown should be called
- at exit time to synch the password on-disk storage, and to free up
- in-memory storage. */
-void e_passwords_shutdown (void);
+/*
+ initialization is now implicit when you call any of the functions
+ below, although this is only correct if the functions are called
+ from the main thread.
+
+ e_passwords_shutdown should be called at exit time to synch the
+ password on-disk storage, and to free up in-memory storage. */
+void e_passwords_init (void);
+void e_passwords_shutdown (void);
+void e_passwords_cancel(void);
void e_passwords_remember_password (const char *component, const char *key);
void e_passwords_add_password (const char *key, const char *passwd);
char *e_passwords_get_password (const char *component, const char *key);
void e_passwords_forget_password (const char *component, const char *key);
void e_passwords_forget_passwords (void);
-void e_passwords_clear_component_passwords (const char *component);
+void e_passwords_clear_passwords (const char *component);
typedef enum {
- E_PASSWORDS_DO_NOT_REMEMBER,
- E_PASSWORDS_REMEMBER_FOR_SESSION,
- E_PASSWORDS_REMEMBER_FOREVER
+ E_PASSWORDS_REMEMBER_NEVER,
+ E_PASSWORDS_REMEMBER_SESSION,
+ E_PASSWORDS_REMEMBER_FOREVER,
+ E_PASSWORDS_REMEMBER_MASK = 0xf,
+
+ /* option bits */
+ E_PASSWORDS_SECRET = 1<<8,
+ E_PASSWORDS_REPROMPT = 1<<9,
} EPasswordsRememberType;
char * e_passwords_ask_password (const char *title,
const char*component_name, const char *key,
- const char *prompt, gboolean secret,
+ const char *prompt,
EPasswordsRememberType remember_type,
gboolean *remember,
GtkWindow *parent);