evolution-data-server/evolution-data-server-1.9.92-e-passwords.patch
2007-09-04 03:16:15 +00:00

1878 lines
51 KiB
Diff

--- evolution-data-server-1.11.92/libedataserverui/e-passwords.c.e-passwords 2007-09-02 14:54:22.000000000 -0400
+++ evolution-data-server-1.11.92/libedataserverui/e-passwords.c 2007-09-03 23:13:10.000000000 -0400
@@ -23,18 +23,29 @@
*/
/*
- * 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 threading model was changed in version 1.11. Here's the details.
*
- * 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.
+ * We now use a dedicated "dispatcher" thread to process password messages.
+ * The callback functions do not use synchronization guards when accessing
+ * the password store, so those functions must only be called from the
+ * dispatcher thread.
*
- * 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.
+ * Message processing behind a visible password dialog is the trickiest
+ * part to get right. We want to, at all costs, avoid repeatedly prompting
+ * the user for the same password. To that end, when the password dialog
+ * for some key 'X' is visible, the dispatcher thread is blocked and
+ * subsequent messages for key 'X' are expedited by redirecting them to a
+ * special "express queue" [1].
+ *
+ * Once the password dialog is closed, all messages in the express queue
+ * are either (depending on the user's response) cancelled or loaded with
+ * the new password and returned to the sender. The express queue is then
+ * closed so that no new messages can enter, and the dispatcher thread
+ * resumes its normal processing.
+ *
+ * [1] Yes, it's a stupid name, but it's the best I could think of. It's
+ * somewhat analogous to an express lane on a freeway because messages
+ * get through faster.
*/
#ifdef HAVE_CONFIG_H
@@ -42,159 +53,381 @@
#endif
#include <string.h>
-#include <libgnome/gnome-config.h>
+#include <gtk/gtk.h>
#include <glib/gi18n-lib.h>
-#include <gtk/gtkversion.h>
-#include <gtk/gtkentry.h>
-#include <gtk/gtkvbox.h>
-#include <gtk/gtkcheckbutton.h>
-#include <gtk/gtkmessagedialog.h>
#include "e-passwords.h"
-#include "libedataserver/e-msgport.h"
+#include "libedataserver/e-flag.h"
#include "libedataserver/e-url.h"
#ifdef WITH_GNOME_KEYRING
#include <gnome-keyring.h>
#endif
-#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
+#define d(x)
-#define d(x) x
+typedef struct _EPassMsg EPassMsg;
+typedef struct _EPassDialogData EPassDialogData;
+typedef void (*EPassCallback) (EPassMsg *msg);
struct _EPassMsg {
- EMsg msg;
- void (*dispatch)(struct _EPassMsg *);
+ /* The 'expedite' flag indicates that the message
+ * is eligible for entry into the express queue. */
- /* input */
- struct _GtkWindow *parent;
- const char *component;
- const char *key;
- const char *title;
- const char *prompt;
- const char *oldpass;
- guint32 flags;
+ /* dispatching */
+ EPassCallback callback;
+ gboolean expedite;
+ EFlag *done;
+
+ /* input/output */
+ const gchar *component;
+ const gchar *key;
+ gchar *password;
+ gpointer data;
+};
- /* output */
- gboolean *remember;
- char *password;
+struct _EPassDialogData {
- /* work variables */
- GtkWidget *entry;
- GtkWidget *check;
- guint ismain:1;
- guint noreply:1; /* supress replies; when calling
- * dispatch functions from others */
+ /* settings */
+ GtkWindow *parent;
+ const gchar *title;
+ const gchar *prompt;
+ gint flags;
+
+ /* input/output */
+ gboolean remember;
+ gint response;
+
+ /* synchronization */
+ EFlag *done;
};
-typedef struct _EPassMsg EPassMsg;
+/* Forward Declarations */
+static void ep_msg_dispatch (EPassMsg *msg);
-static GHashTable *passwords = NULL;
-static GtkDialog *password_dialog = NULL;
-static EDList request_list = E_DLIST_INITIALISER(request_list);
-static int idle_id;
-static int ep_online_state = TRUE;
-
-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);
+static GThreadPool *dispatcher = NULL;
+static GHashTable *password_cache = NULL;
+static gboolean ep_online_state = TRUE;
-static gboolean
-ep_idle_dispatch(void *data)
+/* The queue's lock also guards the key. */
+static const gchar *express_key = NULL;
+static GAsyncQueue *express_queue = NULL;
+
+#define KEY_FILE_GROUP_PREFIX "Passwords-"
+static GKeyFile *key_file = NULL;
+
+static gchar *
+ep_key_file_get_filename (void)
{
- EPassMsg *msg;
+ /* XXX It would be nice to someday move this data elsewhere, or else
+ * fully migrate to GNOME Keyring or whatever software supercedes it.
+ * Evolution is one of the few remaining GNOME-2 applications that
+ * still uses the deprecated ~/.gnome2-private directory. */
- /* 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();
+ return g_build_filename (g_get_home_dir (),
+ ".gnome2_private", "Evolution", NULL);
+}
- msg->dispatch(msg);
+static gchar *
+ep_key_file_get_group (const gchar *component)
+{
+ return g_strconcat (KEY_FILE_GROUP_PREFIX, component, NULL);
+}
- LOCK();
+static gchar *
+ep_key_file_normalize_key (const gchar *key)
+{
+ /* XXX Previous code converted all slashes and equal signs in the
+ * key to underscores for use with "gnome-config" functions. While
+ * it may not be necessary to convert slashes for use with GKeyFile,
+ * and an equal sign was most likely never encountered in a key, we
+ * continue to do the same for backward-compatibility. */
+
+ gchar *normalized_key, *cp;
+
+ normalized_key = g_strdup (key);
+ for (cp = normalized_key; *cp != '\0'; cp++)
+ if (*cp == '/' || *cp == '=')
+ *cp = '_';
+
+ return normalized_key;
+}
+
+static void
+ep_key_file_load (void)
+{
+ gchar *filename;
+ GError *error = NULL;
+
+ filename = ep_key_file_get_filename ();
+
+ if (!g_file_test (filename, G_FILE_TEST_EXISTS))
+ goto exit;
+
+ g_key_file_load_from_file (key_file, filename,
+ G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS,
+ &error);
+
+ if (error != NULL) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
}
- idle_id = 0;
- UNLOCK();
+exit:
+ g_free (filename);
+}
- return FALSE;
+static void
+ep_key_file_save (void)
+{
+ gchar *contents;
+ gchar *filename;
+ gsize length;
+ GError *error = NULL;
+
+ filename = ep_key_file_get_filename ();
+ contents = g_key_file_to_data (key_file, &length, NULL);
+
+ g_file_set_contents (filename, contents, length, &error);
+
+ if (error != NULL) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ g_free (contents);
+ g_free (filename);
}
-static EPassMsg *
-ep_msg_new(void (*dispatch)(EPassMsg *))
+static gchar *
+ep_password_encode (const gchar *password)
{
- EPassMsg *msg;
+ /* XXX The previous Base64 encoding function did not encode the
+ * password's trailing nul byte. This makes decoding the Base64
+ * string into a nul-terminated password more difficult, but we
+ * continue to do it this way for backward-compatibility. */
+
+ gsize length = strlen (password);
+ return g_base64_encode ((const guchar *) password, length);
+}
+
+static gchar *
+ep_password_decode (const gchar *encoded_password)
+{
+ /* XXX The previous Base64 encoding function did not encode the
+ * password's trailing nul byte, so we have to append a nul byte
+ * to the decoded data to make it a nul-terminated string. */
+
+ gchar *password;
+ gsize length;
- e_passwords_init();
+ password = (gchar *) g_base64_decode (encoded_password, &length);
+ password = g_realloc (password, length + 1);
+ password[length] = '\0';
- msg = g_malloc0(sizeof(*msg));
- msg->dispatch = dispatch;
- msg->msg.reply_port = e_msgport_new();
-#ifdef ENABLE_THREADS
- msg->ismain = pthread_equal(pthread_self(), main_thread);
+ return password;
+}
+
+static gpointer
+ep_init (gpointer data)
+{
+ /* Initialize the data structures with unbounded lifetimes. */
+
+ dispatcher = g_thread_pool_new (
+ (GFunc) ep_msg_dispatch, NULL, 1, FALSE, NULL);
+
+ password_cache = g_hash_table_new_full (
+ g_str_hash, g_str_equal, g_free, g_free);
+
+ express_queue = g_async_queue_new ();
+
+#ifdef WITH_GNOME_KEYRING
+ if (!gnome_keyring_is_available ()) {
+ key_file = g_key_file_new ();
+ ep_key_file_load ();
+ }
#else
- msg->ismain = TRUE;
+ key_file = g_key_file_new ();
+ ep_key_file_load ();
#endif
+
+ return NULL;
+}
+
+static EPassMsg *
+ep_msg_new (EPassCallback callback, gboolean expedite)
+{
+ static GOnce once = G_ONCE_INIT;
+ EPassMsg *msg;
+
+ g_once (&once, ep_init, NULL);
+
+ msg = g_slice_new0 (EPassMsg);
+ msg->callback = callback;
+ msg->expedite = expedite;
+ msg->done = e_flag_new ();
+
return msg;
}
static void
-ep_msg_free(EPassMsg *msg)
+ep_msg_dispatch (EPassMsg *msg)
+{
+ msg->callback (msg);
+ e_flag_set (msg->done);
+}
+
+static gboolean
+ep_msg_expedite (EPassMsg *msg)
+{
+ gboolean success = FALSE;
+
+ g_async_queue_lock (express_queue);
+ if (express_key != NULL && strcmp (msg->key, express_key) == 0) {
+ g_async_queue_push_unlocked (express_queue, msg);
+ success = TRUE;
+ }
+ g_async_queue_unlock (express_queue);
+
+ return success;
+}
+
+static void
+ep_msg_send (EPassMsg *msg)
+{
+ GMainContext *context;
+
+ context = g_main_context_default ();
+
+ /* Expedite flag requires a key. */
+ g_assert (!msg->expedite || msg->key != NULL);
+
+ if (!(msg->expedite && ep_msg_expedite (msg)))
+ g_thread_pool_push (dispatcher, msg, NULL);
+
+ /* Don't block the main loop. */
+ if (g_main_context_is_owner (context))
+ while (!e_flag_is_set (msg->done))
+ g_main_context_iteration (context, TRUE);
+ else
+ e_flag_wait (msg->done);
+}
+
+static void
+ep_msg_free (EPassMsg *msg)
{
- e_msgport_destroy(msg->msg.reply_port);
- g_free(msg->password);
- g_free(msg);
+ e_flag_free (msg->done);
+ g_slice_free (EPassMsg, msg);
+}
+
+static EPassDialogData *
+ep_dialog_data_new (GtkWindow *parent, const gchar *title,
+ const gchar *prompt, gboolean remember, gint flags)
+{
+ EPassDialogData *data;
+
+ data = g_slice_new0 (EPassDialogData);
+ data->done = e_flag_new ();
+
+ data->parent = parent;
+ data->title = title;
+ data->prompt = prompt;
+ data->remember = remember;
+ data->flags = flags;
+
+ return data;
}
static void
-ep_msg_send(EPassMsg *msg)
+ep_dialog_data_free (EPassDialogData *data)
+{
+ e_flag_free (data->done);
+ g_slice_free (EPassDialogData, data);
+}
+
+static gboolean
+ep_dialog_run (EPassMsg *msg)
{
- int needidle = 0;
+ /* This function must run in the main thread. */
- LOCK();
- e_dlist_addtail(&request_list, (EDListNode *)&msg->msg);
- if (!idle_id) {
- if (!msg->ismain)
- idle_id = g_idle_add(ep_idle_dispatch, NULL);
+ EPassDialogData *data = msg->data;
+ GtkBox *box;
+ GtkWidget *dialog;
+ GtkWidget *entry;
+ GtkWidget *check_button = NULL;
+ gboolean visible;
+ gint remember;
+
+ visible = !(data->flags & E_PASSWORDS_SECRET);
+ remember = data->flags & E_PASSWORDS_REMEMBER_MASK;
+
+ /* Create a standard message dialog. */
+ dialog = gtk_message_dialog_new (
+ data->parent, 0, GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_OK_CANCEL, "%s", data->prompt);
+ gtk_window_set_title (GTK_WINDOW (dialog), data->title);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+ box = GTK_BOX (GTK_DIALOG (dialog)->vbox);
+
+ /* Add a GtkEntry for the password. */
+ entry = gtk_entry_new ();
+ gtk_box_pack_start (box, entry, TRUE, FALSE, 3);
+ gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
+ gtk_entry_set_visibility (GTK_ENTRY (entry), visible);
+ if (msg->password != NULL) {
+ gtk_entry_set_text (GTK_ENTRY (entry), msg->password);
+ g_free (msg->password);
+ msg->password = NULL;
+ }
+ atk_object_set_description (
+ gtk_widget_get_accessible (entry), data->prompt);
+ gtk_widget_grab_focus (entry);
+ gtk_widget_show (entry);
+
+ /* Add a GtkCheckButton for the "remember" option. */
+ if (remember != E_PASSWORDS_REMEMBER_NEVER) {
+ if (data->flags & E_PASSWORDS_PASSPHRASE)
+ check_button = gtk_check_button_new_with_mnemonic (
+ (remember == E_PASSWORDS_REMEMBER_FOREVER) ?
+ _("_Remember this passphrase") :
+ _("_Remember this passphrase for the "
+ "remainder of this session"));
else
- needidle = 1;
- }
- UNLOCK();
+ check_button = gtk_check_button_new_with_mnemonic (
+ (remember == E_PASSWORDS_REMEMBER_FOREVER) ?
+ _("_Remember this password") :
+ _("_Remember this password for the "
+ "remainder of this session"));
+ gtk_box_pack_start (box, check_button, TRUE, FALSE, 3);
+ gtk_toggle_button_set_active (
+ GTK_TOGGLE_BUTTON (check_button), data->remember);
+ if (data->flags & E_PASSWORDS_DISABLE_REMEMBER)
+ gtk_widget_set_sensitive (check_button, FALSE);
+ gtk_widget_show (check_button);
+ }
+
+ /* Run the dialog and collect the results. */
+ data->response = gtk_dialog_run (GTK_DIALOG (dialog));
+ msg->password = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
+ if (check_button != NULL)
+ data->remember = gtk_toggle_button_get_active (
+ GTK_TOGGLE_BUTTON (check_button));
+ else
+ data->remember = FALSE;
- if (msg->ismain) {
- EPassMsg *m;
+ gtk_widget_destroy (dialog);
+ e_flag_set (data->done);
- 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 {
- EMsg *reply_msg = e_msgport_wait(msg->msg.reply_port);
- g_assert(reply_msg == &msg->msg);
- }
+ return FALSE;
}
-/* the functions that actually do the work */
+/* The rest of these static functions must run in the dispatcher thread. */
+
#ifdef WITH_GNOME_KEYRING
static void
-ep_clear_passwords_keyring(EPassMsg *msg)
+ep_clear_passwords_keyring (EPassMsg *msg)
{
GnomeKeyringAttributeList *attributes;
GnomeKeyringResult result;
@@ -203,11 +436,8 @@
result = gnome_keyring_get_default_keyring_sync (&default_keyring);
if (!default_keyring) {
- if (gnome_keyring_create_sync ("default", NULL) != GNOME_KEYRING_RESULT_OK) {
- if (!msg->noreply)
- e_msgport_reply(&msg->msg);
- return;
- }
+ if (gnome_keyring_create_sync ("default", NULL) != GNOME_KEYRING_RESULT_OK)
+ return;
default_keyring = g_strdup ("default");
}
@@ -232,38 +462,44 @@
}
g_free (default_keyring);
- if (!msg->noreply)
- e_msgport_reply(&msg->msg);
}
#endif
+
static void
-ep_clear_passwords_file(EPassMsg *msg)
+ep_clear_passwords_keyfile (EPassMsg *msg)
{
- char *path;
+ gchar *group;
+ GError *error = NULL;
- path = g_strdup_printf ("/Evolution/Passwords-%s", msg->component);
+ group = ep_key_file_get_group (msg->component);
- gnome_config_private_clean_section (path);
- gnome_config_private_sync_file ("/Evolution");
-
- g_free (path);
+ g_key_file_remove_group (key_file, group, &error);
+ if (error == NULL)
+ ep_key_file_save ();
+ else {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
- if (!msg->noreply)
- e_msgport_reply(&msg->msg);
+ g_free (group);
}
-static gboolean
-free_entry (gpointer key, gpointer value, gpointer user_data)
+static void
+ep_clear_passwords (EPassMsg *msg)
{
- g_free (key);
- memset (value, 0, strlen (value));
- g_free (value);
- return TRUE;
+#ifdef WITH_GNOME_KEYRING
+ if (gnome_keyring_is_available ())
+ ep_clear_passwords_keyring (msg);
+ else
+ ep_clear_passwords_keyfile (msg);
+#else
+ ep_clear_passwords_keyfile (msg);
+#endif
}
#ifdef WITH_GNOME_KEYRING
static void
-ep_forget_passwords_keyring(EPassMsg *msg)
+ep_forget_passwords_keyring (EPassMsg *msg)
{
GnomeKeyringAttributeList *attributes;
GnomeKeyringResult result;
@@ -272,11 +508,8 @@
result = gnome_keyring_get_default_keyring_sync (&default_keyring);
if (!default_keyring) {
- if (gnome_keyring_create_sync ("default", NULL) != GNOME_KEYRING_RESULT_OK) {
- if (!msg->noreply)
- e_msgport_reply(&msg->msg);
- return;
- }
+ if (gnome_keyring_create_sync ("default", NULL) != GNOME_KEYRING_RESULT_OK)
+ return;
default_keyring = g_strdup ("default");
}
d(g_print("Get Default %d\n", result));
@@ -301,68 +534,53 @@
g_free (default_keyring);
/* free up the session passwords */
- g_hash_table_foreach_remove (passwords, free_entry, NULL);
-
- if (!msg->noreply)
- e_msgport_reply(&msg->msg);
+ g_hash_table_remove_all (password_cache);
}
#endif
static void
-ep_forget_passwords_file(EPassMsg *msg)
+ep_forget_passwords_keyfile (EPassMsg *msg)
{
- void *it;
- char *key;
+ gchar **groups;
+ gsize length, ii;
- it = gnome_config_private_init_iterator_sections("/Evolution");
- while ( (it = gnome_config_iterator_next(it, &key, NULL)) ) {
- if (0 == strncmp(key, "Passwords-", 10)) {
- char *section = g_strdup_printf("/Evolution/%s", key);
+ g_hash_table_remove_all (password_cache);
- gnome_config_private_clean_section (section);
- g_free(section);
- }
- g_free(key);
+ groups = g_key_file_get_groups (key_file, &length);
+ for (ii = 0; ii < length; ii++) {
+ if (!g_str_has_prefix (groups[ii], KEY_FILE_GROUP_PREFIX))
+ continue;
+ g_key_file_remove_group (key_file, groups[ii], NULL);
}
-
- gnome_config_private_sync_file ("/Evolution");
-
- /* free up the session passwords */
- g_hash_table_foreach_remove (passwords, free_entry, NULL);
-
- if (!msg->noreply)
- e_msgport_reply(&msg->msg);
+ ep_key_file_save ();
+ g_strfreev (groups);
}
-static char *
-password_path (const char *component_name, const char *key)
+static void
+ep_forget_passwords (EPassMsg *msg)
{
- char *keycopy, *path;
- int i;
- keycopy = g_strdup (key);
-
- for (i = 0; i < strlen (keycopy); i ++)
- if (keycopy[i] == '/' || keycopy[i] =='=')
- keycopy[i] = '_';
-
- path = g_strdup_printf ("/Evolution/Passwords-%s/%s", component_name, keycopy);
-
- g_free (keycopy);
-
- return path;
+#ifdef WITH_GNOME_KEYRING
+ if (gnome_keyring_is_available ())
+ ep_forget_passwords_keyring (msg);
+ else
+ ep_forget_passwords_keyfile (msg);
+#else
+ ep_forget_passwords_keyfile (msg);
+#endif
}
#ifdef WITH_GNOME_KEYRING
static void
-ep_remember_password_keyring(EPassMsg *msg)
+ep_remember_password_keyring (EPassMsg *msg)
{
- gpointer okey, value;
+ gpointer value;
- if (g_hash_table_lookup_extended (passwords, msg->key, &okey, &value)) {
+ value = g_hash_table_lookup (password_cache, msg->key);
+ if (value != NULL) {
/* add it to the on-disk cache of passwords */
GnomeKeyringAttributeList *attributes;
GnomeKeyringResult result;
- EUri *uri = e_uri_new (okey);
+ EUri *uri = e_uri_new (msg->key);
guint32 item_id;
if (!strcmp (uri->protocol, "ldap") && !uri->user) {
@@ -394,48 +612,48 @@
gnome_keyring_attribute_list_free (attributes);
/* now remove it from our session hash */
- g_hash_table_remove (passwords, msg->key);
- g_free (okey);
- g_free (value);
+ g_hash_table_remove (password_cache, msg->key);
e_uri_free (uri);
}
-
- if (!msg->noreply)
- e_msgport_reply(&msg->msg);
}
#endif
static void
-ep_remember_password_file(EPassMsg *msg)
+ep_remember_password_keyfile (EPassMsg *msg)
{
- gpointer okey, value;
- char *path, *pass64;
- int len, state, save;
+ gchar *group, *key, *password;
- 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);
+ password = g_hash_table_lookup (password_cache, msg->key);
+ if (password == NULL) {
+ g_warning ("Password for key \"%s\" not found", msg->key);
+ return;
+ }
- len = strlen (value);
- pass64 = g_malloc0 ((len + 2) * 4 / 3 + 1);
- state = save = 0;
- base64_encode_close (value, len, FALSE, (guchar *)pass64, &state, &save);
-
- gnome_config_private_set_string (path, pass64);
- g_free (path);
- g_free (pass64);
+ group = ep_key_file_get_group (msg->component);
+ key = ep_key_file_normalize_key (msg->key);
+ password = ep_password_encode (password);
- /* now remove it from our session hash */
- g_hash_table_remove (passwords, msg->key);
- g_free (okey);
- g_free (value);
+ g_hash_table_remove (password_cache, msg->key);
+ g_key_file_set_string (key_file, group, key, password);
+ ep_key_file_save ();
- gnome_config_private_sync_file ("/Evolution");
- }
+ g_free (group);
+ g_free (key);
+ g_free (password);
+}
- if (!msg->noreply)
- e_msgport_reply(&msg->msg);
+static void
+ep_remember_password (EPassMsg *msg)
+{
+#ifdef WITH_GNOME_KEYRING
+ if (gnome_keyring_is_available ())
+ ep_remember_password_keyring (msg);
+ else
+ ep_remember_password_keyfile (msg);
+#else
+ ep_remember_password_keyfile (msg);
+#endif
}
#ifdef WITH_GNOME_KEYRING
@@ -446,7 +664,6 @@
GnomeKeyringResult result;
GList *matches = NULL, *tmp;
char *default_keyring = NULL;
- gpointer okey, value;
EUri *uri = e_uri_new (msg->key);
if (!strcmp (uri->protocol, "ldap") && !uri->user) {
@@ -460,12 +677,7 @@
uri->user = keycopy;
}
- 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);
- }
+ g_hash_table_remove (password_cache, msg->key);
if (!uri->host && !uri->user)
/* No need to remove from keyring for pass phrases */
@@ -524,36 +736,45 @@
g_free (default_keyring);
exit:
- if (!msg->noreply)
- e_msgport_reply(&msg->msg);
-
e_uri_free(uri);
}
#endif
static void
-ep_forget_password_file (EPassMsg *msg)
+ep_forget_password_keyfile (EPassMsg *msg)
{
- gpointer okey, value;
- char *path;
+ gchar *group, *key;
+ GError *error = NULL;
- 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);
-
- if (!msg->noreply)
- e_msgport_reply(&msg->msg);
+ g_hash_table_remove (password_cache, msg->key);
+
+ group = ep_key_file_get_group (msg->component);
+ key = ep_key_file_normalize_key (msg->key);
+
+ g_key_file_remove_key (key_file, group, key, &error);
+ if (error == NULL)
+ ep_key_file_save ();
+ else {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ g_free (group);
+ g_free (key);
}
+static void
+ep_forget_password (EPassMsg *msg)
+{
+#ifdef WITH_GNOME_KEYRING
+ if (gnome_keyring_is_available ())
+ ep_forget_password_keyring (msg);
+ else
+ ep_forget_password_keyfile (msg);
+#else
+ ep_forget_password_keyfile (msg);
+#endif
+}
#ifdef WITH_GNOME_KEYRING
static void
@@ -562,11 +783,11 @@
char *passwd;
GnomeKeyringAttributeList *attributes;
GnomeKeyringResult result;
- GList *matches = NULL, *tmp;
+ GList *matches = NULL, *tmp;
- passwd = g_hash_table_lookup (passwords, msg->key);
+ passwd = g_hash_table_lookup (password_cache, msg->key);
if (passwd) {
- msg->password = g_strdup(passwd);
+ msg->password = g_strdup (passwd);
} else {
EUri *uri = e_uri_new (msg->key);
@@ -630,288 +851,154 @@
e_uri_free (uri);
}
-
- if (!msg->noreply)
- e_msgport_reply(&msg->msg);
}
#endif
static void
-ep_get_password_file (EPassMsg *msg)
+ep_get_password_keyfile (EPassMsg *msg)
{
- char *path, *passwd;
- char *encoded = NULL;
+ gchar *group, *key, *password;
+ GError *error = NULL;
- passwd = g_hash_table_lookup (passwords, msg->key);
- if (passwd) {
- msg->password = g_strdup(passwd);
+ password = g_hash_table_lookup (password_cache, msg->key);
+ if (password != NULL) {
+ msg->password = g_strdup (password);
+ return;
+ }
+
+ group = ep_key_file_get_group (msg->component);
+ key = ep_key_file_normalize_key (msg->key);
+
+ password = g_key_file_get_string (key_file, group, key, &error);
+ if (password != NULL) {
+ msg->password = ep_password_decode (password);
+ g_free (password);
} 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);
- }
+ g_warning ("%s", error->message);
+ g_error_free (error);
}
- if (!msg->noreply)
- e_msgport_reply(&msg->msg);
+ g_free (group);
+ g_free (key);
}
static void
-ep_add_password (EPassMsg *msg)
+ep_get_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);
- }
+#ifdef WITH_GNOME_KEYRING
+ if (gnome_keyring_is_available ())
+ ep_get_password_keyring (msg);
+ else
+ ep_get_password_keyfile (msg);
+#else
+ ep_get_password_keyfile (msg);
+#endif
+}
- g_hash_table_insert (passwords, g_strdup (msg->key), g_strdup (msg->oldpass));
+static void
+ep_add_password (EPassMsg *msg)
+{
+ gchar *key = g_strdup (msg->key);
+ gchar *password = g_strdup (msg->password);
- if (!msg->noreply)
- e_msgport_reply(&msg->msg);
+ g_hash_table_insert (password_cache, key, password);
}
-static void ep_ask_password(EPassMsg *msg);
-
static void
-pass_response(GtkDialog *dialog, int response, void *data)
+ep_ask_password (EPassMsg *msg)
{
- EPassMsg *msg = data;
- int type = msg->flags & E_PASSWORDS_REMEMBER_MASK;
- EDList pending = E_DLIST_INITIALISER(pending);
- EPassMsg *mw, *mn;
+ EPassDialogData *data = msg->data;
+ gchar *password;
+ gint remember;
- if (response == GTK_RESPONSE_OK) {
- msg->password = g_strdup(gtk_entry_get_text((GtkEntry *)msg->entry));
+ /* Open the express queue for this key. This allows us to catch
+ * incoming operations on this key while waiting for the user to
+ * provide a password. Once we have the password, immediately
+ * process any messages in the express queue. */
+ g_async_queue_lock (express_queue);
+ express_key = msg->key;
+ g_async_queue_unlock (express_queue);
- if (type != E_PASSWORDS_REMEMBER_NEVER) {
- int noreply = msg->noreply;
+ if (data->flags & E_PASSWORDS_REPROMPT)
+ ep_get_password (msg);
- *msg->remember = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (msg->check));
+ /* Run the password dialog in the main thread. */
+ g_idle_add ((GSourceFunc) ep_dialog_run, msg);
- msg->noreply = 1;
-
- if (*msg->remember || type == E_PASSWORDS_REMEMBER_FOREVER) {
- msg->oldpass = msg->password;
- ep_add_password(msg);
- }
-#ifdef WITH_GNOME_KEYRING
- if (*msg->remember && type == E_PASSWORDS_REMEMBER_FOREVER) {
- if (gnome_keyring_is_available())
- ep_remember_password_keyring(msg);
- else
- ep_remember_password_file(msg);
- }
-#else
- if (*msg->remember && type == E_PASSWORDS_REMEMBER_FOREVER)
- ep_remember_password_file(msg);
-#endif
+ /* Wait for the user to respond. */
+ e_flag_wait (data->done);
- msg->noreply = noreply;
- }
+ /* If the user cancelled the dialog then we need to dispatch
+ * any messages that we trapped in the express queue. */
+ if (data->response != GTK_RESPONSE_OK) {
+ g_async_queue_lock (express_queue);
+ express_key = NULL;
+ while ((msg = g_async_queue_try_pop_unlocked (express_queue)))
+ ep_msg_dispatch (msg);
+ g_async_queue_unlock (express_queue);
+ return;
}
- gtk_widget_destroy((GtkWidget *)dialog);
- password_dialog = NULL;
+ remember = data->flags & E_PASSWORDS_REMEMBER_MASK;
- /* 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) {
-#ifdef WITH_GNOME_KEYRING
- if ((mw->dispatch == (gnome_keyring_is_available() ? ep_forget_password_keyring : ep_forget_password_file)
-#else
- if ((mw->dispatch == ep_forget_password_file
-#endif
-#ifdef WITH_GNOME_KEYRING
- || mw->dispatch == (gnome_keyring_is_available() ? ep_get_password_keyring : ep_get_password_file)
-#else
- || mw->dispatch == ep_get_password_file
-#endif
- || 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 (remember == E_PASSWORDS_REMEMBER_NEVER)
+ goto cleanup;
- if (!msg->noreply)
- e_msgport_reply(&msg->msg);
+ if (data->remember || remember == E_PASSWORDS_REMEMBER_FOREVER)
+ ep_add_password (msg);
- ep_idle_dispatch(NULL);
-}
+ if (data->remember && remember == E_PASSWORDS_REMEMBER_FOREVER)
+ ep_remember_password (msg);
-static void
-ep_ask_password(EPassMsg *msg)
-{
- GtkWidget *vbox;
- int type = msg->flags & E_PASSWORDS_REMEMBER_MASK;
- guint noreply = msg->noreply;
- AtkObject *a11y;
-
- 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,
- "%s", msg->prompt);
- gtk_window_set_title(GTK_WINDOW(password_dialog), msg->title);
-
- gtk_widget_ensure_style (GTK_WIDGET (password_dialog));
- gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (password_dialog)->vbox), 0);
- gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (password_dialog)->action_area), 12);
-
- gtk_dialog_set_default_response(password_dialog, GTK_RESPONSE_OK);
+cleanup:
- vbox = gtk_vbox_new (FALSE, 12);
- 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, 12);
-
- msg->entry = gtk_entry_new ();
+ password = g_strdup (msg->password);
- a11y = gtk_widget_get_accessible (msg->entry);
- atk_object_set_description (a11y, msg->prompt);
- 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)) {
-#ifdef WITH_GNOME_KEYRING
- if (gnome_keyring_is_available())
- ep_get_password_keyring(msg);
- else
- ep_get_password_file(msg);
-#else
- ep_get_password_file(msg);
-#endif
- if (msg->password) {
- gtk_entry_set_text ((GtkEntry *) msg->entry, msg->password);
- g_free (msg->password);
- msg->password = NULL;
- }
+ /* Close the express queue and process any messages there. */
+ g_async_queue_lock (express_queue);
+ express_key = NULL;
+ while ((msg = g_async_queue_try_pop_unlocked (express_queue))) {
+ msg->password = g_strdup (password);
+ e_flag_set (msg->done);
}
+ g_async_queue_unlock (express_queue);
- /* static password, shouldn't be remembered between sessions,
- but will be remembered within the session beyond our control */
- if (type != E_PASSWORDS_REMEMBER_NEVER) {
- if (msg->flags & E_PASSWORDS_PASSPHRASE) {
- msg->check = gtk_check_button_new_with_mnemonic(type == E_PASSWORDS_REMEMBER_FOREVER
- ? _("_Remember this passphrase")
- : _("_Remember this passphrase for the remainder of this session"));
- } else {
- 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);
- if ((msg->flags & E_PASSWORDS_DISABLE_REMEMBER))
- gtk_widget_set_sensitive(msg->check, FALSE);
- gtk_widget_show (msg->check);
- }
-
- msg->noreply = noreply;
-
- g_signal_connect(password_dialog, "response", G_CALLBACK (pass_response), msg);
-
- if (msg->parent)
- gtk_dialog_run (GTK_DIALOG (password_dialog));
- else
- gtk_widget_show((GtkWidget *)password_dialog);
+ g_free (password);
}
-
/**
* e_passwords_init:
*
- * Initializes the e_passwords routines. Must be called before any other
- * e_passwords_* function.
+ * This function is here for backward-compatibility. It does nothing.
**/
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.
+ * e_passwords_shutdown:
+ *
+ * This function is here for backward-compatibility. It does nothing.
**/
void
-e_passwords_cancel(void)
+e_passwords_shutdown (void)
{
- EPassMsg *msg;
-
- LOCK();
- while ((msg = (EPassMsg *)e_dlist_remhead(&request_list)))
- e_msgport_reply(&msg->msg);
- UNLOCK();
-
- if (password_dialog)
- gtk_dialog_response(password_dialog,GTK_RESPONSE_CANCEL);
}
/**
- * e_passwords_shutdown:
- *
- * Cleanup routine to call before exiting.
+ * e_passwords_cancel:
+ *
+ * This function is here for backward-compatibility. It does nothing.
**/
void
-e_passwords_shutdown (void)
+e_passwords_cancel(void)
{
-#ifdef WITH_GNOME_KEYRING
- /* shouldn't need this really - everything is synchronous */
- if (!gnome_keyring_is_available())
- gnome_config_private_sync_file ("/Evolution");
-#else
- gnome_config_private_sync_file ("/Evolution");
-#endif
- 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_set_online:
- * @state:
+ * @online:
*
* Set the offline-state of the application. This is a work-around
* for having the backends fully offline aware, and returns a
@@ -920,10 +1007,11 @@
* FIXME: This is not a permanent api, review post 2.0.
**/
void
-e_passwords_set_online(int state)
+e_passwords_set_online (gboolean online)
{
- ep_online_state = state;
- /* TODO: we could check that a request is open and close it, or maybe who cares */
+ /* TODO We could check that a request is open and close it,
+ * or maybe who cares */
+ ep_online_state = online;
}
/**
@@ -934,151 +1022,138 @@
void
e_passwords_forget_passwords (void)
{
-#ifdef WITH_GNOME_KEYRING
- EPassMsg *msg = ep_msg_new(gnome_keyring_is_available() ? ep_forget_passwords_keyring : ep_forget_passwords_file);
-#else
- EPassMsg *msg = ep_msg_new(ep_forget_passwords_file);
-#endif
-
- ep_msg_send(msg);
- ep_msg_free(msg);
+ EPassMsg *msg;
+
+ msg = ep_msg_new (ep_forget_passwords, FALSE);
+
+ ep_msg_send (msg);
+ ep_msg_free (msg);
}
/**
* e_passwords_clear_passwords:
+ * @component: component name of the caller
*
* Forgets all disk cached passwords for the component.
**/
void
-e_passwords_clear_passwords (const char *component_name)
+e_passwords_clear_passwords (const gchar *component)
{
-#ifdef WITH_GNOME_KEYRING
- EPassMsg *msg = ep_msg_new(gnome_keyring_is_available() ? ep_clear_passwords_keyring : ep_clear_passwords_file);
-#else
- EPassMsg *msg = ep_msg_new(ep_clear_passwords_file);
-#endif
+ EPassMsg *msg;
- msg->component = component_name;
- ep_msg_send(msg);
- ep_msg_free(msg);
+ g_return_if_fail (component != NULL);
+
+ msg = ep_msg_new (ep_clear_passwords, FALSE);
+ msg->component = component;
+
+ ep_msg_send (msg);
+ ep_msg_free (msg);
}
/**
* e_passwords_remember_password:
+ * @component: component name of the caller
* @key: the key
*
* Saves the password associated with @key to disk.
**/
void
-e_passwords_remember_password (const char *component_name, const char *key)
+e_passwords_remember_password (const gchar *component, const gchar *key)
{
EPassMsg *msg;
- g_return_if_fail(component_name != NULL);
- g_return_if_fail(key != NULL);
+ g_return_if_fail (component != NULL);
+ g_return_if_fail (key != NULL);
-#ifdef WITH_GNOME_KEYRING
- msg = ep_msg_new(gnome_keyring_is_available() ? ep_remember_password_keyring : ep_remember_password_file);
-#else
- msg = ep_msg_new(ep_remember_password_file);
-#endif
- msg->component = component_name;
+ msg = ep_msg_new (ep_remember_password, FALSE);
+ msg->component = component;
msg->key = key;
- ep_msg_send(msg);
- ep_msg_free(msg);
+ ep_msg_send (msg);
+ ep_msg_free (msg);
}
/**
* e_passwords_forget_password:
+ * @component: component name of the caller
* @key: the key
*
* Forgets the password associated with @key, in memory and on disk.
**/
void
-e_passwords_forget_password (const char *component_name, const char *key)
+e_passwords_forget_password (const gchar *component, const gchar *key)
{
EPassMsg *msg;
- g_return_if_fail(component_name != NULL);
- g_return_if_fail(key != NULL);
+ g_return_if_fail (component != NULL);
+ g_return_if_fail (key != NULL);
-#ifdef WITH_GNOME_KEYRING
- msg = ep_msg_new(gnome_keyring_is_available() ? ep_forget_password_keyring : ep_forget_password_file);
-#else
- msg = ep_msg_new(ep_forget_password_file);
-#endif
- msg->component = component_name;
+ msg = ep_msg_new (ep_forget_password, TRUE);
+ msg->component = component;
msg->key = key;
- ep_msg_send(msg);
- ep_msg_free(msg);
+ ep_msg_send (msg);
+ ep_msg_free (msg);
}
/**
* e_passwords_get_password:
+ * @component: component name of the caller
* @key: the key
*
* Return value: the password associated with @key, or %NULL. Caller
* must free the returned password.
**/
char *
-e_passwords_get_password (const char *component_name, const char *key)
+e_passwords_get_password (const gchar *component, const gchar *key)
{
EPassMsg *msg;
- char *passwd;
-
- g_return_val_if_fail(component_name != NULL, NULL);
- g_return_val_if_fail(key != NULL, NULL);
+ char *password;
-#ifdef WITH_GNOME_KEYRING
- msg = ep_msg_new(gnome_keyring_is_available() ? ep_get_password_keyring : ep_get_password_file);
-#else
- msg = ep_msg_new(ep_get_password_file);
-#endif
+ g_return_val_if_fail (component != NULL, NULL);
+ g_return_val_if_fail (key != NULL, NULL);
- msg->component = component_name;
+ msg = ep_msg_new (ep_get_password, TRUE);
+ msg->component = component;
msg->key = key;
- ep_msg_send(msg);
+ ep_msg_send (msg);
+ password = msg->password;
+ ep_msg_free (msg);
- passwd = msg->password;
- msg->password = NULL;
- ep_msg_free(msg);
-
- return passwd;
+ return password;
}
/**
* e_passwords_add_password:
* @key: a key
- * @passwd: the password for @key
+ * @password: the password for @key
*
* This stores the @key/@passwd pair in the current session's password
* hash.
**/
void
-e_passwords_add_password (const char *key, const char *passwd)
+e_passwords_add_password (const gchar *key, const gchar *password)
{
EPassMsg *msg;
- g_return_if_fail(key != NULL);
- g_return_if_fail(passwd != NULL);
+ g_return_if_fail (key != NULL);
+ g_return_if_fail (password != NULL);
- msg = ep_msg_new(ep_add_password);
+ msg = ep_msg_new (ep_add_password, FALSE);
msg->key = key;
- msg->oldpass = passwd;
+ msg->password = g_strdup (password);
- ep_msg_send(msg);
- ep_msg_free(msg);
+ ep_msg_send (msg);
+ g_free (msg->password);
+ ep_msg_free (msg);
}
/**
* e_passwords_ask_password:
* @title: title for the password dialog
- * @component_name: the name of the component for which we're storing
- * the password (e.g. Mail, Addressbook, etc.)
- * @key: key to store the password under
+ * @component: component name of the caller
+ * @key: key to store the password under, or NULL
* @prompt: prompt string
* @type: whether or not to offer to remember the password,
* and for how long.
@@ -1093,245 +1168,44 @@
* return value is non-%NULL and @remember_type is not
* E_PASSWORDS_DO_NOT_REMEMBER.
**/
-char *
-e_passwords_ask_password (const char *title, const char *component_name,
- const char *key,
- const char *prompt,
+gchar *
+e_passwords_ask_password (const gchar *title,
+ const gchar *component,
+ const gchar *key,
+ const gchar *prompt,
EPasswordsRememberType type,
- gboolean *remember,
+ gboolean *p_remember,
GtkWindow *parent)
{
- char *passwd;
EPassMsg *msg;
-
- g_return_val_if_fail (component_name != NULL, NULL);
- g_return_val_if_fail (key != NULL, NULL);
+ EPassDialogData *data;
+ gboolean remember;
+ gchar *password;
+
+ g_return_val_if_fail (title != NULL, NULL);
+ g_return_val_if_fail (component != NULL, NULL);
+ g_return_val_if_fail (prompt != NULL, NULL);
if ((type & E_PASSWORDS_ONLINE) && !ep_online_state)
return NULL;
- 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;
-}
-
-
-
-static char *base64_alphabet =
-"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-static unsigned char camel_mime_base64_rank[256] = {
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255,
- 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
- 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-};
-
-/* call this when finished encoding everything, to
- flush off the last little bit */
-static int
-base64_encode_close(unsigned char *in, int inlen, gboolean break_lines, unsigned char *out, int *state, int *save)
-{
- int c1, c2;
- unsigned char *outptr = out;
-
- if (inlen>0)
- outptr += base64_encode_step(in, inlen, break_lines, outptr, state, save);
-
- c1 = ((unsigned char *)save)[1];
- c2 = ((unsigned char *)save)[2];
-
- switch (((char *)save)[0]) {
- case 2:
- outptr[2] = base64_alphabet[ ( (c2 &0x0f) << 2 ) ];
- g_assert(outptr[2] != 0);
- goto skip;
- case 1:
- outptr[2] = '=';
- skip:
- outptr[0] = base64_alphabet[ c1 >> 2 ];
- outptr[1] = base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 )];
- outptr[3] = '=';
- outptr += 4;
- break;
- }
- if (break_lines)
- *outptr++ = '\n';
-
- *save = 0;
- *state = 0;
-
- return outptr-out;
-}
-
-/*
- performs an 'encode step', only encodes blocks of 3 characters to the
- output at a time, saves left-over state in state and save (initialise to
- 0 on first invocation).
-*/
-static int
-base64_encode_step(unsigned char *in, int len, gboolean break_lines, unsigned char *out, int *state, int *save)
-{
- register unsigned char *inptr, *outptr;
-
- if (len<=0)
- return 0;
-
- inptr = in;
- outptr = out;
-
- if (len + ((char *)save)[0] > 2) {
- unsigned char *inend = in+len-2;
- register int c1, c2, c3;
- register int already;
-
- already = *state;
-
- switch (((char *)save)[0]) {
- case 1: c1 = ((unsigned char *)save)[1]; goto skip1;
- case 2: c1 = ((unsigned char *)save)[1];
- c2 = ((unsigned char *)save)[2]; goto skip2;
- }
-
- /* yes, we jump into the loop, no i'm not going to change it, it's beautiful! */
- while (inptr < inend) {
- c1 = *inptr++;
- skip1:
- c2 = *inptr++;
- skip2:
- c3 = *inptr++;
- *outptr++ = base64_alphabet[ c1 >> 2 ];
- *outptr++ = base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 ) ];
- *outptr++ = base64_alphabet[ ( (c2 &0x0f) << 2 ) | (c3 >> 6) ];
- *outptr++ = base64_alphabet[ c3 & 0x3f ];
- /* this is a bit ugly ... */
- if (break_lines && (++already)>=19) {
- *outptr++='\n';
- already = 0;
- }
- }
-
- ((char *)save)[0] = 0;
- len = 2-(inptr-inend);
- *state = already;
- }
-
- if (len>0) {
- register char *saveout;
-
- /* points to the slot for the next char to save */
- saveout = & (((char *)save)[1]) + ((char *)save)[0];
-
- /* len can only be 0 1 or 2 */
- switch(len) {
- case 2: *saveout++ = *inptr++;
- case 1: *saveout++ = *inptr++;
- }
- ((char *)save)[0]+=len;
- }
+ remember = (p_remember != NULL) ? *p_remember : FALSE;
+ data = ep_dialog_data_new (parent, title, prompt, remember, type);
- return outptr-out;
-}
+ msg = ep_msg_new (ep_ask_password, TRUE);
+ msg->component = component;
+ msg->key = (key != NULL) ? key : "";
+ msg->data = data;
+ ep_msg_send (msg);
+ password = msg->password;
+ remember = data->remember;
+ ep_msg_free (msg);
-/**
- * base64_decode_step: decode a chunk of base64 encoded data
- * @in: input stream
- * @len: max length of data to decode
- * @out: output stream
- * @state: holds the number of bits that are stored in @save
- * @save: leftover bits that have not yet been decoded
- *
- * Decodes a chunk of base64 encoded data
- **/
-static int
-base64_decode_step(unsigned char *in, int len, unsigned char *out, int *state, unsigned int *save)
-{
- register unsigned char *inptr, *outptr;
- unsigned char *inend, c;
- register unsigned int v;
- int i;
-
- inend = in+len;
- outptr = out;
-
- /* convert 4 base64 bytes to 3 normal bytes */
- v=*save;
- i=*state;
- inptr = in;
- while (inptr<inend) {
- c = camel_mime_base64_rank[*inptr++];
- if (c != 0xff) {
- v = (v<<6) | c;
- i++;
- if (i==4) {
- *outptr++ = v>>16;
- *outptr++ = v>>8;
- *outptr++ = v;
- i=0;
- }
- }
- }
+ ep_dialog_data_free (data);
- *save = v;
- *state = i;
+ if (p_remember != NULL)
+ *p_remember = remember;
- /* quick scan back for '=' on the end somewhere */
- /* fortunately we can drop 1 output char for each trailing = (upto 2) */
- i=2;
- while (inptr>in && i) {
- inptr--;
- if (camel_mime_base64_rank[*inptr] != 0xff) {
- if (*inptr == '=')
- outptr--;
- i--;
- }
- }
-
- /* if i!= 0 then there is a truncation error! */
- return outptr-out;
-}
-
-static char *
-decode_base64 (char *base64)
-{
- guchar *plain;
- char *pad = "==";
- int len, out, state;
- unsigned int save;
-
- len = strlen (base64);
- plain = g_malloc0 (len);
- state = save = 0;
- out = base64_decode_step ((guchar *)base64, len, plain, &state, &save);
- if (len % 4) {
- base64_decode_step ((guchar *)pad, 4 - len % 4, plain + out,
- &state, &save);
- }
-
- return (char *)plain;
+ return password;
}
--- evolution-data-server-1.11.92/libedataserverui/e-passwords.h.e-passwords 2007-09-02 14:54:22.000000000 -0400
+++ evolution-data-server-1.11.92/libedataserverui/e-passwords.h 2007-09-03 23:13:10.000000000 -0400
@@ -28,45 +28,65 @@
G_BEGIN_DECLS
-/*
- 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_set_online(int state);
-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_passwords (const char *component);
-
+/**
+ * EPasswordsRememberType:
+ * @E_PASSWORDS_REMEMBER_NEVER:
+ * Do not remember the password.
+ * @E_PASSWORDS_REMEMBER_SESSION:
+ * Remember the password for this session only.
+ * @E_PASSWORDS_REMEMBER_FOREVER:
+ * Remember the password across multiple sessions.
+ * @E_PASSWORDS_REMEMBER_MASK:
+ * Mask value separates the mutually-exclusive values
+ * of the enumeration from the flags.
+ * @E_PASSWORDS_SECRET:
+ * Do not show the password as it's being typed.
+ * @E_PASSWORDS_REPROMPT:
+ * Populate the dialog with the current password (if one exists).
+ * @E_PASSWORDS_ONLINE:
+ * Only prompt the user for a password if we're online.
+ * @E_PASSWORDS_DISABLE_REMEMBER:
+ * Disable the "remember password" option on the dialog.
+ * @E_PASSWORDS_PASSPHRASE:
+ * Ask for a passphrase instead of a password.
+ **/
typedef enum {
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,
- E_PASSWORDS_ONLINE = 1<<10, /* only ask if we're online */
- E_PASSWORDS_DISABLE_REMEMBER = 1<<11, /* disable the 'remember password' checkbox */
- E_PASSWORDS_PASSPHRASE = 1<<12, /* We are asking a passphrase */
+ /* flags */
+ E_PASSWORDS_SECRET = 1 << 8,
+ E_PASSWORDS_REPROMPT = 1 << 9,
+ E_PASSWORDS_ONLINE = 1 << 10,
+ E_PASSWORDS_DISABLE_REMEMBER = 1 << 11,
+ E_PASSWORDS_PASSPHRASE = 1 << 12,
} EPasswordsRememberType;
-char * e_passwords_ask_password (const char *title,
- const char*component_name, const char *key,
- const char *prompt,
- EPasswordsRememberType remember_type,
- gboolean *remember,
- GtkWindow *parent);
+#ifndef EDS_DISABLE_DEPRECATED
+void e_passwords_init (void);
+void e_passwords_shutdown (void);
+void e_passwords_cancel (void);
+#endif
+void e_passwords_set_online (gboolean online);
+void e_passwords_remember_password (const gchar *component,
+ const gchar *key);
+void e_passwords_add_password (const gchar *key,
+ const gchar *password);
+gchar * e_passwords_get_password (const gchar *component,
+ const gchar *key);
+void e_passwords_forget_password (const gchar *component,
+ const gchar *key);
+void e_passwords_forget_passwords (void);
+void e_passwords_clear_passwords (const gchar *component);
+gchar * e_passwords_ask_password (const gchar *title,
+ const gchar *component,
+ const gchar *key,
+ const gchar *prompt,
+ EPasswordsRememberType remember_type,
+ gboolean *remember,
+ GtkWindow *parent);
G_END_DECLS
--- evolution-data-server-1.11.92/libedataserver/e-msgport.h.e-passwords 2007-07-05 02:01:55.000000000 -0400
+++ evolution-data-server-1.11.92/libedataserver/e-msgport.h 2007-09-03 23:13:10.000000000 -0400
@@ -54,7 +54,7 @@
/* header for any message */
typedef struct _EMsg {
- EDListNode ln;
+ EDListNode ln; /* deprecated */
EMsgPort *reply_port;
gint flags;
} EMsg;