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:
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
192
mail/mail-mt.c
192
mail/mail-mt.c
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user