Completely re-done. We now hae a completely async dialogue when requested

2001-10-23    <NotZed@Ximian.com>

        * mail-session.c (get_password): Completely re-done.  We now hae a
        completely async dialogue when requested from antoehr thread, and
        dont use gtk_main() if we can avoid it (which is normally the
        case).  This stuff is only partially finished, and will mena the
        removal of the same from mail-mt.c, and the mail_user_message()
        code will be moved here and changed to work in a similar way.

        * mail-callbacks.c (empty_trash): Dont try and connect to remote
        stores just to get the trash.  Also, always run empty trash async,
        and make sure we unref the trash.
        (empty_trash): Hmm, dont unref the trash, causes a problem on
        exit, i suspect something else is doing funky unrefs on it.

        * mail-tools.c (mail_tool_get_trash): Pass a 'connect' arg, tell
        it whether it should tryand connect or not to the parent service,
        if it isn't already connected.

        * component-factory.c (owner_unset_cb): Dont try wait_all here,
        could potentially deadlock.
        (idle_quit): Keep returning TRUE if we have outstanding
        processing.  Note that this may busy-wait during exit processign
        with busy tasks :(
        (idle_quit): Keep calling ourselves till we no longer get called
        (i.e. gtk_main really quits).

        * mail-mt.c (mail_msg_active): New function, returns TRUE if
        events are still active/outstanding.
        (do_op_status): @$@$#@@!#@!!  didn't unlock the mail_msg_lock if
        data->activity was NULL and we had no global_shell_client anymore!
        Also shortcut processing if this is going to be the case.
        (mail_msg_init): Setup a temporary other gui_port for redoing with
        new semantics password, user message and progress reporting.
        (mail_get_password): #ifdef'd out all this code temporarily, till
        it gets fully moved to mail-session.c

2001-10-22    <NotZed@Ximian.com>

        * component-factory.c (owner_set_cb): Dont call enable_interaction
        here.
        (interactive_cb): But here instead, let the shell tell us when its
        ok to go interactive.

svn path=/trunk/; revision=13933
This commit is contained in:
3
2001-10-23 06:28:27 +00:00
committed by Michael Zucci
parent 51d6b1c4ea
commit 343f36cffe
8 changed files with 491 additions and 120 deletions

View File

@ -1,3 +1,47 @@
2001-10-23 <NotZed@Ximian.com>
* mail-session.c (get_password): Completely re-done. We now hae a
completely async dialogue when requested from antoehr thread, and
dont use gtk_main() if we can avoid it (which is normally the
case). This stuff is only partially finished, and will mena the
removal of the same from mail-mt.c, and the mail_user_message()
code will be moved here and changed to work in a similar way.
* mail-callbacks.c (empty_trash): Dont try and connect to remote
stores just to get the trash. Also, always run empty trash async,
and make sure we unref the trash.
(empty_trash): Hmm, dont unref the trash, causes a problem on
exit, i suspect something else is doing funky unrefs on it.
* mail-tools.c (mail_tool_get_trash): Pass a 'connect' arg, tell
it whether it should tryand connect or not to the parent service,
if it isn't already connected.
* component-factory.c (owner_unset_cb): Dont try wait_all here,
could potentially deadlock.
(idle_quit): Keep returning TRUE if we have outstanding
processing. Note that this may busy-wait during exit processign
with busy tasks :(
(idle_quit): Keep calling ourselves till we no longer get called
(i.e. gtk_main really quits).
* mail-mt.c (mail_msg_active): New function, returns TRUE if
events are still active/outstanding.
(do_op_status): @$@$#@@!#@!! didn't unlock the mail_msg_lock if
data->activity was NULL and we had no global_shell_client anymore!
Also shortcut processing if this is going to be the case.
(mail_msg_init): Setup a temporary other gui_port for redoing with
new semantics password, user message and progress reporting.
(mail_get_password): #ifdef'd out all this code temporarily, till
it gets fully moved to mail-session.c
2001-10-22 <NotZed@Ximian.com>
* component-factory.c (owner_set_cb): Dont call enable_interaction
here.
(interactive_cb): But here instead, let the shell tell us when its
ok to go interactive.
2001-10-22 Jeffrey Stedfast <fejj@ximian.com>
* mail-format.c (write_one_text_plain_chunk): Oops, revert my

View File

@ -718,8 +718,6 @@ owner_set_cb (EvolutionShellComponent *shell_component,
got_folder, standard_folders[i].folder, mail_thread_new));
}
mail_session_enable_interaction (TRUE);
mail_autoreceive_setup ();
if (mail_config_is_corrupt ()) {
@ -753,6 +751,12 @@ debug_cb (EvolutionShellComponent *shell_component, gpointer user_data)
camel_verbose_debug = 1;
}
static void
interactive_cb (EvolutionShellComponent *shell_component, gboolean on, gpointer user_data)
{
mail_session_enable_interaction(on);
}
static void
handle_external_uri_cb (EvolutionShellComponent *shell_component,
const char *uri,
@ -788,19 +792,32 @@ user_create_new_item_cb (EvolutionShellComponent *shell_component,
static gboolean
idle_quit (gpointer user_data)
{
mail_msg_wait_all();
if (e_list_length (folder_browser_factory_get_control_list ()))
return TRUE;
g_hash_table_foreach (storages_hash, free_storage, NULL);
g_hash_table_destroy (storages_hash);
mail_vfolder_shutdown ();
static int shutdown_vfolder = FALSE;
static int shutdown_shutdown = FALSE;
if (!shutdown_shutdown) {
if (e_list_length (folder_browser_factory_get_control_list ()))
return TRUE;
if (mail_msg_active(-1)) {
/* short sleep? */
return TRUE;
}
if (!shutdown_vfolder) {
shutdown_vfolder = TRUE;
mail_vfolder_shutdown();
return TRUE;
}
shutdown_shutdown = TRUE;
g_hash_table_foreach (storages_hash, free_storage, NULL);
g_hash_table_destroy (storages_hash);
}
gtk_main_quit ();
return FALSE;
return TRUE;
}
static void owner_unset_cb (EvolutionShellComponent *shell_component, gpointer user_data);
@ -814,6 +831,7 @@ static struct {
{ "owner_set", owner_set_cb, },
{ "owner_unset", owner_unset_cb, },
{ "debug", debug_cb, },
{ "interactive", interactive_cb },
{ "destroy", owner_unset_cb, },
{ "handle_external_uri", handle_external_uri_cb, },
{ "user_create_new_item", user_create_new_item_cb }
@ -830,14 +848,12 @@ owner_unset_cb (EvolutionShellComponent *shell_component, gpointer user_data)
if (mail_config_get_empty_trash_on_exit ())
empty_trash (NULL, NULL, NULL);
mail_msg_wait_all();
unref_standard_folders ();
mail_importer_uninit ();
global_shell_client = NULL;
mail_session_enable_interaction (FALSE);
g_idle_add_full (G_PRIORITY_LOW, idle_quit, NULL, NULL);
}

View File

@ -2391,13 +2391,9 @@ empty_trash (BonoboUIComponent *uih, void *user_data, const char *path)
CamelFolder *vtrash;
FolderBrowser *fb;
CamelException ex;
gboolean async;
fb = user_data ? FOLDER_BROWSER (user_data) : NULL;
/* the only time all three args are NULL is for empty-on-exit */
async = !(uih == NULL && fb == NULL && path == NULL);
if (fb && !confirm_expunge (fb))
return;
@ -2415,13 +2411,10 @@ empty_trash (BonoboUIComponent *uih, void *user_data, const char *path)
/* make sure this store is a remote store */
if (provider->flags & CAMEL_PROVIDER_IS_STORAGE &&
provider->flags & CAMEL_PROVIDER_IS_REMOTE) {
vtrash = mail_tool_get_trash (account->source->url, &ex);
vtrash = mail_tool_get_trash (account->source->url, FALSE, &ex);
if (vtrash) {
if (async)
mail_expunge_folder (vtrash, empty_trash_expunged_cb, NULL);
else
camel_folder_sync (vtrash, TRUE, NULL);
mail_expunge_folder (vtrash, empty_trash_expunged_cb, NULL);
}
}
}
@ -2433,12 +2426,9 @@ empty_trash (BonoboUIComponent *uih, void *user_data, const char *path)
}
/* Now empty the local trash folder */
vtrash = mail_tool_get_trash ("file:/", &ex);
vtrash = mail_tool_get_trash ("file:/", TRUE, &ex);
if (vtrash) {
if (async)
mail_expunge_folder (vtrash, empty_trash_expunged_cb, NULL);
else
camel_folder_sync (vtrash, TRUE, NULL);
mail_expunge_folder (vtrash, empty_trash_expunged_cb, NULL);
}
camel_exception_clear (&ex);

View File

@ -35,6 +35,7 @@
/*#define MALLOC_CHECK*/
#define LOG_OPS
#define LOG_LOCKS
#define d(x)
static void set_stop(int sensitive);
@ -42,9 +43,13 @@ static void mail_enable_stop(void);
static void mail_disable_stop(void);
static void mail_operation_status(struct _CamelOperation *op, const char *what, int pc, void *data);
#ifdef LOG_LOCKS
#define MAIL_MT_LOCK(x) (log_locks?fprintf(log, "%ld: lock " # x "\n", pthread_self()):0, pthread_mutex_lock(&x))
#define MAIL_MT_UNLOCK(x) (log_locks?fprintf(log, "%ld: unlock " # x "\n", pthread_self()): 0, pthread_mutex_unlock(&x))
#else
#define MAIL_MT_LOCK(x) pthread_mutex_lock(&x)
#define MAIL_MT_UNLOCK(x) pthread_mutex_unlock(&x)
#endif
extern EvolutionShellClient *global_shell_client;
/* background operation status stuff */
@ -62,10 +67,11 @@ static GdkPixbuf *progress_icon[2] = { NULL, NULL };
/* mail_msg stuff */
#ifdef LOG_OPS
static FILE *log;
static int log_ops, log_locks, log_init;
#endif
static unsigned int mail_msg_seq; /* sequence number of each message */
static GHashTable *mail_msg_active; /* table of active messages, must hold mail_msg_lock to access */
static GHashTable *mail_msg_active_table; /* table of active messages, must hold mail_msg_lock to access */
static pthread_mutex_t mail_msg_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t mail_msg_cond = PTHREAD_COND_INITIALIZER;
@ -81,13 +87,26 @@ void *mail_msg_new(mail_msg_op_t *ops, EMsgPort *reply_port, size_t size)
MAIL_MT_LOCK(mail_msg_lock);
#ifdef LOG_OPS
if (log == NULL && getenv("EVOLUTION_MAIL_LOG_OPS") != NULL) {
#if defined(LOG_OPS) || defined(LOG_LOCKS)
if (!log_init) {
time_t now = time(0);
log_init = TRUE;
log_ops = getenv("EVOLUTION_MAIL_LOG_OPS") != NULL;
log_locks = getenv("EVOLUTION_MAIL_LOG_LOCKS") != NULL;
log = fopen("evolution-mail-ops.log", "w+");
setvbuf(log, NULL, _IOLBF, 0);
fprintf(log, "Started evolution-mail: %s\n", ctime(&now));
#ifdef LOG_OPS
if (log_ops)
fprintf(log, "Logging async operations\n");
#endif
#ifdef LOG_LOCKS
if (log_locks) {
fprintf(log, "Logging lock operations, mail_gui_thread = %ld\n\n", mail_gui_thread);
fprintf(log, "%ld: lock mail_msg_lock\n", pthread_self());
}
#endif
g_warning("Logging mail operations to evolution-mail-ops.log");
}
#endif
@ -99,12 +118,12 @@ void *mail_msg_new(mail_msg_op_t *ops, EMsgPort *reply_port, size_t size)
camel_exception_init(&msg->ex);
msg->priv = g_malloc0(sizeof(*msg->priv));
g_hash_table_insert(mail_msg_active, (void *)msg->seq, msg);
g_hash_table_insert(mail_msg_active_table, (void *)msg->seq, msg);
d(printf("New message %p\n", msg));
#ifdef LOG_OPS
if (log)
if (log_ops)
fprintf(log, "%p: New\n", msg);
#endif
MAIL_MT_UNLOCK(mail_msg_lock);
@ -161,10 +180,10 @@ void mail_msg_free(void *msg)
MAIL_MT_LOCK(mail_msg_lock);
#ifdef LOG_OPS
if (log)
if (log_ops)
fprintf(log, "%p: Free\n", msg);
#endif
g_hash_table_remove(mail_msg_active, (void *)m->seq);
g_hash_table_remove(mail_msg_active_table, (void *)m->seq);
pthread_cond_broadcast(&mail_msg_cond);
/* We need to make sure we dont lose a reference here YUCK YUCK */
@ -250,7 +269,7 @@ void mail_msg_cancel(unsigned int msgid)
struct _mail_msg *m;
MAIL_MT_LOCK(mail_msg_lock);
m = g_hash_table_lookup(mail_msg_active, (void *)msgid);
m = g_hash_table_lookup(mail_msg_active_table, (void *)msgid);
if (m)
camel_operation_cancel(m->cancel);
@ -268,32 +287,46 @@ void mail_msg_wait(unsigned int msgid)
if (ismain) {
MAIL_MT_LOCK(mail_msg_lock);
m = g_hash_table_lookup(mail_msg_active, (void *)msgid);
m = g_hash_table_lookup(mail_msg_active_table, (void *)msgid);
while (m) {
MAIL_MT_UNLOCK(mail_msg_lock);
gtk_main_iteration();
MAIL_MT_LOCK(mail_msg_lock);
m = g_hash_table_lookup(mail_msg_active, (void *)msgid);
m = g_hash_table_lookup(mail_msg_active_table, (void *)msgid);
}
MAIL_MT_UNLOCK(mail_msg_lock);
} else {
MAIL_MT_LOCK(mail_msg_lock);
m = g_hash_table_lookup(mail_msg_active, (void *)msgid);
m = g_hash_table_lookup(mail_msg_active_table, (void *)msgid);
while (m) {
pthread_cond_wait(&mail_msg_cond, &mail_msg_lock);
m = g_hash_table_lookup(mail_msg_active, (void *)msgid);
m = g_hash_table_lookup(mail_msg_active_table, (void *)msgid);
}
MAIL_MT_UNLOCK(mail_msg_lock);
}
}
int mail_msg_active(unsigned int msgid)
{
int active;
MAIL_MT_LOCK(mail_msg_lock);
if (msgid == (unsigned int)-1)
active = g_hash_table_size(mail_msg_active_table) > 0;
else
active = g_hash_table_lookup(mail_msg_active_table, (void *)msgid) != NULL;
MAIL_MT_UNLOCK(mail_msg_lock);
return active;
}
void mail_msg_wait_all(void)
{
int ismain = pthread_self() == mail_gui_thread;
if (ismain) {
MAIL_MT_LOCK(mail_msg_lock);
while (g_hash_table_size(mail_msg_active) > 0) {
while (g_hash_table_size(mail_msg_active_table) > 0) {
MAIL_MT_UNLOCK(mail_msg_lock);
gtk_main_iteration();
MAIL_MT_LOCK(mail_msg_lock);
@ -301,7 +334,7 @@ void mail_msg_wait_all(void)
MAIL_MT_UNLOCK(mail_msg_lock);
} else {
MAIL_MT_LOCK(mail_msg_lock);
while (g_hash_table_size(mail_msg_active) > 0) {
while (g_hash_table_size(mail_msg_active_table) > 0) {
pthread_cond_wait(&mail_msg_cond, &mail_msg_lock);
}
MAIL_MT_UNLOCK(mail_msg_lock);
@ -310,6 +343,12 @@ void mail_msg_wait_all(void)
EMsgPort *mail_gui_port;
static GIOChannel *mail_gui_channel;
static guint mail_gui_watch;
EMsgPort *mail_gui_port2;
static GIOChannel *mail_gui_channel2;
static guint mail_gui_watch2;
EMsgPort *mail_gui_reply_port;
static GIOChannel *mail_gui_reply_channel;
@ -333,7 +372,7 @@ mail_msgport_replied(GIOChannel *source, GIOCondition cond, void *d)
#endif
#ifdef LOG_OPS
if (log)
if (log_ops)
fprintf(log, "%p: Replied to GUI thread\n", m);
#endif
@ -360,7 +399,7 @@ mail_msgport_received(GIOChannel *source, GIOCondition cond, void *d)
#endif
#ifdef LOG_OPS
if (log)
if (log_ops)
fprintf(log, "%p: Received at GUI thread\n", m);
#endif
@ -378,6 +417,29 @@ mail_msgport_received(GIOChannel *source, GIOCondition cond, void *d)
return TRUE;
}
/* Test code, lighterwight, more configurable calls */
static gboolean
mail_msgport_received2(GIOChannel *source, GIOCondition cond, void *d)
{
EMsgPort *port = (EMsgPort *)d;
mail_msg_t *m;
while (( m = (mail_msg_t *)e_msgport_get(port))) {
#ifdef LOG_OPS
if (log_ops)
fprintf(log, "%p: Received at GUI2 thread\n", m);
#endif
if (m->ops->receive_msg)
m->ops->receive_msg(m);
else
mail_msg_free(m);
}
return TRUE;
}
static void
mail_msg_destroy(EThread *e, EMsg *msg, void *data)
{
@ -407,7 +469,7 @@ mail_msg_received(EThread *e, EMsg *msg, void *data)
char *text = m->ops->describe_msg(m, FALSE);
#ifdef LOG_OPS
if (log)
if (log_ops)
fprintf(log, "%p: Received at thread %ld: '%s'\n", m, pthread_self(), text);
#endif
@ -418,7 +480,7 @@ mail_msg_received(EThread *e, EMsg *msg, void *data)
}
#ifdef LOG_OPS
else
if (log)
if (log_ops)
fprintf(log, "%p: Received at thread %ld\n", m, pthread_self());
#endif
@ -457,7 +519,13 @@ void mail_msg_init(void)
mail_gui_port = e_msgport_new();
mail_gui_channel = g_io_channel_unix_new(e_msgport_fd(mail_gui_port));
g_io_add_watch(mail_gui_channel, G_IO_IN, mail_msgport_received, mail_gui_port);
mail_gui_watch = g_io_add_watch(mail_gui_channel, G_IO_IN, mail_msgport_received, mail_gui_port);
/* experimental temporary */
mail_gui_port2 = e_msgport_new();
mail_gui_channel2 = g_io_channel_unix_new(e_msgport_fd(mail_gui_port2));
mail_gui_watch2 = g_io_add_watch(mail_gui_channel2, G_IO_IN, mail_msgport_received2, mail_gui_port2);
mail_thread_queued = e_thread_new(E_THREAD_QUEUE);
e_thread_set_msg_destroy(mail_thread_queued, mail_msg_destroy, 0);
@ -475,7 +543,7 @@ void mail_msg_init(void)
e_thread_set_reply_port(mail_thread_new, mail_gui_reply_port);
e_thread_set_queue_limit(mail_thread_new, 10);
mail_msg_active = g_hash_table_new(NULL, NULL);
mail_msg_active_table = g_hash_table_new(NULL, NULL);
mail_gui_thread = pthread_self();
mail_async_event = mail_async_event_new();
@ -488,6 +556,13 @@ static pthread_mutex_t status_lock = PTHREAD_MUTEX_INITIALIZER;
/* ********************************************************************** */
#if 0
static GnomeDialog *password_dialogue = NULL;
static EDList password_list = E_DLIST_INITIALISER(password_list);
static struct _pass_msg *password_current = NULL;
static void do_get_pass (struct _mail_msg *mm);
struct _pass_msg {
struct _mail_msg msg;
const char *prompt;
@ -496,12 +571,15 @@ struct _pass_msg {
char *result;
char *service_url;
GtkWidget *check;
int inmain;
};
static void
pass_got (char *string, void *data)
{
struct _pass_msg *m = data;
printf("password got! string = '%s'\n", string?string:"<nil>");
if (string) {
MailConfigService *service = NULL;
@ -533,6 +611,18 @@ pass_got (char *string, void *data)
if (m->cache)
*(m->cache) = remember;
}
if (!m->inmain)
e_msgport_reply((EMsg *)m);
password_dialogue = NULL;
m = e_dlist_remhead(&password_list);
if (m) {
printf("Have queued password request, showing now the other is finished\n");
do_get_pass(m);
}
}
@ -546,10 +636,17 @@ do_get_pass (struct _mail_msg *mm)
GList *children, *iter;
gboolean show;
char *title;
/* If we already have a password_dialogue up, save this request till later */
if (!m->inmain && password_dialogue) {
e_dlist_addtail(&password_list, (EDListNode *)mm);
return;
}
password_current = m;
/* this api is just awful ... hence the hacks */
dialogue = gnome_request_dialog (m->secret, m->prompt, NULL,
0, pass_got, m, NULL);
dialogue = gnome_request_dialog (m->secret, m->prompt, NULL, 0, pass_got, m, NULL);
/* Remember the password? */
check = gtk_check_button_new_with_label (m->service_url ? _("Remember this password") :
@ -577,14 +674,12 @@ do_get_pass (struct _mail_msg *mm)
/* do some dirty stuff to put the checkbutton after the entry */
entry = NULL;
children = gtk_container_children (GTK_CONTAINER (GNOME_DIALOG (dialogue)->vbox));
for (iter = children; iter; iter = iter->next) {
if (GTK_IS_ENTRY (iter->data)) {
entry = GTK_WIDGET (iter->data);
break;
}
}
g_list_free (children);
if (entry) {
@ -592,8 +687,7 @@ do_get_pass (struct _mail_msg *mm)
gtk_container_remove (GTK_CONTAINER (GNOME_DIALOG (dialogue)->vbox), entry);
}
gtk_box_pack_end (GTK_BOX (GNOME_DIALOG (dialogue)->vbox),
check, TRUE, FALSE, 0);
gtk_box_pack_end (GTK_BOX (GNOME_DIALOG (dialogue)->vbox), check, TRUE, FALSE, 0);
if (entry) {
gtk_box_pack_end (GTK_BOX (GNOME_DIALOG (dialogue)->vbox), entry, TRUE, FALSE, 0);
@ -617,10 +711,16 @@ do_get_pass (struct _mail_msg *mm)
gtk_window_set_title (GTK_WINDOW (dialogue), title);
g_free (title);
gnome_dialog_run_and_close ((GnomeDialog *)dialogue);
/*gtk_widget_show(dialogue);*/
if (m->inmain) {
printf("showing dialogue in main\n");
password_current = NULL;
gnome_dialog_run_and_close ((GnomeDialog *)dialogue);
e_msgport_reply((EMsg *)m);
} else {
printf("showing dialogue async\n");
gtk_widget_show(dialogue);
}
}
static void
@ -653,23 +753,19 @@ mail_get_password (CamelService *service, const char *prompt, gboolean secret, g
m->prompt = prompt;
m->secret = secret;
m->cache = cache;
m->inmain = pthread_self() == mail_gui_thread;
if (service) {
m->service_url = camel_url_to_string (service->url, CAMEL_URL_HIDE_ALL);
} else
m->service_url = NULL;
if (pthread_self () == mail_gui_thread) {
if (m->inmain) {
do_get_pass ((struct _mail_msg *)m);
r = m;
} else {
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
/* we want this single-threaded, this is the easiest way to do it without blocking ? */
pthread_mutex_lock (&lock);
e_msgport_put (mail_gui_port, (EMsg *)m);
e_msgport_put (mail_gui_port2, (EMsg *)m);
e_msgport_wait (pass_reply);
r = (struct _pass_msg *)e_msgport_get (pass_reply);
pthread_mutex_unlock (&lock);
}
g_assert (r == m);
@ -682,6 +778,7 @@ mail_get_password (CamelService *service, const char *prompt, gboolean secret, g
return ret;
}
#endif
/* ******************** */
@ -948,7 +1045,6 @@ void *mail_call_main(mail_call_t type, MailMainFunc func, ...)
return ret;
}
/* ********************************************************************** */
/* locked via status_lock */
static int busy_state;
@ -1015,8 +1111,10 @@ static void do_op_status(struct _mail_msg *mm)
MAIL_MT_LOCK (mail_msg_lock);
msg = g_hash_table_lookup (mail_msg_active, m->data);
if (msg == NULL) {
msg = g_hash_table_lookup (mail_msg_active_table, m->data);
/* shortcut processing, i.e. if we have no global_shell_client and no activity, we can't create one */
if (msg == NULL || (msg->priv->activity == NULL && global_shell_client == NULL)) {
MAIL_MT_UNLOCK (mail_msg_lock);
return;
}
@ -1092,15 +1190,15 @@ static void do_op_status(struct _mail_msg *mm)
}
return;
}
}
activity = data->activity;
if (activity) {
} else if (data->activity) {
activity = data->activity;
gtk_object_ref (GTK_OBJECT (activity));
MAIL_MT_UNLOCK (mail_msg_lock);
evolution_activity_client_update (activity, out, (double)(pc/100.0));
gtk_object_unref (GTK_OBJECT (activity));
} else {
MAIL_MT_UNLOCK (mail_msg_lock);
}
}

View File

@ -58,6 +58,7 @@ void mail_msg_check_error(void *msg);
void mail_msg_cancel(unsigned int msgid);
void mail_msg_wait(unsigned int msgid);
void mail_msg_wait_all(void);
int mail_msg_active(unsigned int msgid);
/* request a string/password */
char *mail_get_password (CamelService *service, const char *prompt,

View File

@ -39,6 +39,8 @@
#include "mail-mt.h"
#include "e-util/e-passwords.h"
#define d(x)
CamelSession *session;
@ -130,55 +132,267 @@ make_key (CamelService *service, const char *item)
return key;
}
static char *
main_get_password (CamelSession *session, const char *prompt, gboolean secret,
CamelService *service, const char *item, CamelException *ex)
/* ********************************************************************** */
static GnomeDialog *password_dialogue = NULL;
static EDList password_list = E_DLIST_INITIALISER(password_list);
static struct _pass_msg *password_current = NULL;
static int password_destroy_id;
struct _pass_msg {
struct _mail_msg msg;
CamelSession *session;
const char *prompt;
gboolean secret;
CamelService *service;
const char *item;
CamelException *ex;
char *service_url;
char *key;
GtkWidget *check;
char *result;
int ismain;
};
static void do_get_pass(struct _mail_msg *mm);
static void
pass_got (char *string, void *data)
{
MailSession *mail_session = MAIL_SESSION (session);
gboolean cache = TRUE;
char *key, *ans;
struct _pass_msg *m = data;
if (string) {
MailConfigService *service = NULL;
const MailConfigAccount *mca;
gboolean remember;
m->result = g_strdup (string);
remember = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (m->check));
if (m->service_url) {
mca = mail_config_get_account_by_source_url (m->service_url);
if (mca) {
service = mca->source;
} else {
mca = mail_config_get_account_by_transport_url (m->service_url);
if (mca)
service = mca->transport;
}
if (service) {
mail_config_service_set_save_passwd (service, remember);
/* set `remember' to TRUE because people don't want to have to
re-enter their passwords for this session even if they told
us not to cache their passwords in the dialog...*sigh* */
remember = TRUE;
}
}
if (remember)
e_passwords_add_password(m->key, m->result);
} else {
camel_exception_set(m->ex, CAMEL_EXCEPTION_USER_CANCEL, _("User canceled operation."));
}
if (password_destroy_id) {
gtk_signal_disconnect((GtkObject *)password_dialogue, password_destroy_id);
password_destroy_id = 0;
}
password_dialogue = NULL;
e_msgport_reply((EMsg *)m);
if ((m = (struct _pass_msg *)e_dlist_remhead(&password_list)))
do_get_pass((struct _mail_msg *)m);
}
static void
request_password_deleted(GtkWidget *w, struct _pass_msg *m)
{
password_destroy_id = 0;
pass_got(NULL, m);
}
static void
request_password(struct _pass_msg *m)
{
const MailConfigAccount *mca = NULL;
GtkWidget *dialogue;
GtkWidget *check, *entry;
GList *children, *iter;
gboolean show;
char *title;
/* If we already have a password_dialogue up, save this request till later */
if (!m->ismain && password_dialogue) {
e_dlist_addtail(&password_list, (EDListNode *)m);
return;
}
password_current = m;
/* FIXME: Remove this total snot */
/* this api is just awful ... hence the major hacks */
password_dialogue = dialogue = gnome_request_dialog (m->secret, m->prompt, NULL, 0, pass_got, m, NULL);
/* cant bleieve how @!@#!@# 5this api is, it doesn't handle this for you, BLAH! */
password_destroy_id = gtk_signal_connect((GtkObject *)dialogue, "destroy", request_password_deleted, m);
/* Remember the password? */
check = gtk_check_button_new_with_label (m->service_url ? _("Remember this password") :
_("Remember this password for the remainder of this session"));
show = TRUE;
if (!strcmp (item, "popb4smtp_uri")) {
char *url = camel_url_to_string(service->url, 0);
if (m->service_url) {
mca = mail_config_get_account_by_source_url(m->service_url);
if (mca)
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), mca->source->save_passwd);
else {
mca = mail_config_get_account_by_transport_url (m->service_url);
if (mca)
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), mca->transport->save_passwd);
else {
d(printf ("Cannot figure out which account owns URL \"%s\"\n", m->service_url));
show = FALSE;
}
}
}
if (show)
gtk_widget_show (check);
/* do some dirty stuff to put the checkbutton after the entry */
entry = NULL;
children = gtk_container_children (GTK_CONTAINER (GNOME_DIALOG (dialogue)->vbox));
for (iter = children; iter; iter = iter->next) {
if (GTK_IS_ENTRY (iter->data)) {
entry = GTK_WIDGET (iter->data);
break;
}
}
g_list_free (children);
if (entry) {
gtk_object_ref (GTK_OBJECT (entry));
gtk_container_remove (GTK_CONTAINER (GNOME_DIALOG (dialogue)->vbox), entry);
}
gtk_box_pack_end (GTK_BOX (GNOME_DIALOG (dialogue)->vbox), check, TRUE, FALSE, 0);
if (entry) {
gtk_box_pack_end (GTK_BOX (GNOME_DIALOG (dialogue)->vbox), entry, TRUE, FALSE, 0);
gtk_widget_grab_focus (entry);
gtk_object_unref (GTK_OBJECT (entry));
}
m->check = check;
if (mca) {
char *name;
name = e_utf8_to_gtk_string (GTK_WIDGET (dialogue), mca->name);
title = g_strdup_printf (_("Enter Password for %s"), name);
g_free (name);
} else
title = g_strdup (_("Enter Password"));
gtk_window_set_title (GTK_WINDOW (dialogue), title);
g_free (title);
if (m->ismain) {
password_current = NULL;
gnome_dialog_run_and_close ((GnomeDialog *)dialogue);
} else {
gtk_widget_show(dialogue);
}
}
static void
do_get_pass(struct _mail_msg *mm)
{
struct _pass_msg *m = (struct _pass_msg *)mm;
MailSession *mail_session = MAIL_SESSION (m->session);
if (!strcmp (m->item, "popb4smtp_uri")) {
char *url = camel_url_to_string(m->service->url, 0);
const MailConfigAccount *account = mail_config_get_account_by_transport_url(url);
g_free(url);
if (account == NULL)
return NULL;
return g_strdup(account->source->url);
if (account)
m->result = g_strdup(account->source->url);
} else if (m->key) {
m->result = e_passwords_get_password(m->key);
if (m->result == NULL) {
if (mail_session->interaction_enabled) {
request_password(m);
return;
}
}
}
key = make_key (service, item);
if (!key)
return NULL;
ans = e_passwords_get_password (key);
if (ans) {
g_free (key);
return ans;
}
if (!mail_session->interaction_enabled ||
!(ans = mail_get_password (service, prompt, secret, &cache))) {
g_free (key);
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
_("User canceled operation."));
return NULL;
}
if (cache)
e_passwords_add_password (key, ans);
return ans;
e_msgport_reply((EMsg *)mm);
}
static char *
get_password (CamelSession *session, const char *prompt, gboolean secret,
CamelService *service, const char *item, CamelException *ex)
static void
do_free_pass(struct _mail_msg *mm)
{
return (char *)mail_call_main(MAIL_CALL_p_ppippp, (MailMainFunc)main_get_password,
session, prompt, secret, service, item, ex);
struct _pass_msg *m = (struct _pass_msg *)mm;
g_free(m->service_url);
g_free(m->key);
}
static struct _mail_msg_op get_pass_op = {
NULL,
do_get_pass,
NULL,
do_free_pass,
};
static char *
get_password (CamelSession *session, const char *prompt, gboolean secret, CamelService *service, const char *item, CamelException *ex)
{
struct _pass_msg *m, *r;
EMsgPort *pass_reply;
char *ret;
/* We setup an async request and send it off, and wait for it to return */
/* If we're really in main, we dont of course ...
... but this shouldn't be allowed because of locking issues */
pass_reply = e_msgport_new ();
m = mail_msg_new(&get_pass_op, pass_reply, sizeof(struct _pass_msg));
m->ismain = pthread_self() == mail_gui_thread;
m->session = session;
m->prompt = prompt;
m->secret = secret;
m->service = service;
m->item = item;
m->ex = ex;
if (service)
m->service_url = camel_url_to_string (service->url, CAMEL_URL_HIDE_ALL);
m->key = make_key(service, item);
if (m->ismain)
do_get_pass(m);
else {
extern EMsgPort *mail_gui_port2;
e_msgport_put(mail_gui_port2, (EMsg *)m);
}
e_msgport_wait(pass_reply);
r = (struct _pass_msg *)e_msgport_get(pass_reply);
g_assert(m == r);
ret = m->result;
mail_msg_free(m);
e_msgport_destroy(pass_reply);
return ret;
}
static void

View File

@ -93,16 +93,24 @@ mail_tool_get_inbox (const gchar *url, CamelException *ex)
}
CamelFolder *
mail_tool_get_trash (const gchar *url, CamelException *ex)
mail_tool_get_trash (const gchar *url, int connect, CamelException *ex)
{
CamelStore *store;
CamelFolder *trash;
store = camel_session_get_store (session, url, ex);
if (connect)
store = camel_session_get_store (session, url, ex);
else
store = (CamelStore *)camel_session_get_service(session, url, CAMEL_PROVIDER_STORE, ex);
if (!store)
return NULL;
trash = camel_store_get_trash (store, ex);
if (connect || ((CamelService *)store)->status == CAMEL_SERVICE_CONNECTED)
trash = camel_store_get_trash (store, ex);
else
trash = NULL;
camel_object_unref (CAMEL_OBJECT (store));
return trash;

View File

@ -47,7 +47,7 @@ CamelFolder *mail_tool_get_local_inbox (CamelException *ex);
CamelFolder *mail_tool_get_inbox (const gchar *url, CamelException *ex);
/* Get the "trash" for a url (uses global session) */
CamelFolder *mail_tool_get_trash (const gchar *url, CamelException *ex);
CamelFolder *mail_tool_get_trash (const gchar *url, int connect, CamelException *ex);
/* Does a camel_movemail into the local movemail folder
* and returns the path to the new movemail folder that was created. which shoudl be freed later */