Files
evolution/mail/mail-ops.c
Dan Winship 88aa6978a3 This bug was so much fun to fix the first time that I decided to
fix it again.

	2000-07-11  Dan Winship  <danw@helixcode.com>

		* mail-ops.c (real_send_mail): Set the post_send_data flag
		rather than toggling it. (Maybe we'll need more control
		over it later, but for now, the only flag we set is
		"replied", and we want that set, not toggled.)

svn path=/trunk/; revision=5445
2000-09-15 13:28:43 +00:00

2593 lines
68 KiB
C

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* mail-ops.c: callbacks for the mail toolbar/menus */
/*
* Author :
* Dan Winship <danw@helixcode.com>
* Peter Williams <peterw@helixcode.com>
*
* Copyright 2000 Helix Code, Inc. (http://www.helixcode.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <config.h>
#include <gnome.h>
#include <ctype.h>
#include "mail.h"
#include "mail-threads.h"
#include "mail-tools.h"
#include "mail-ops.h"
#include "composer/e-msg-composer.h"
/* ** FETCH MAIL ********************************************************** */
typedef struct fetch_mail_input_s
{
gchar *source_url;
gboolean keep_on_server;
CamelFolder *destination;
gpointer hook_func;
gpointer hook_data;
}
fetch_mail_input_t;
typedef struct fetch_mail_data_s {
gboolean empty;
} fetch_mail_data_t;
static gchar *describe_fetch_mail (gpointer in_data, gboolean gerund);
static void setup_fetch_mail (gpointer in_data, gpointer op_data,
CamelException *ex);
static void do_fetch_mail (gpointer in_data, gpointer op_data,
CamelException *ex);
static void cleanup_fetch_mail (gpointer in_data, gpointer op_data,
CamelException *ex);
static gchar *
describe_fetch_mail (gpointer in_data, gboolean gerund)
{
fetch_mail_input_t *input = (fetch_mail_input_t *) in_data;
char *name;
/*source = camel_session_get_store (session, input->source_url, NULL);
*if (source) {
* name = camel_service_get_name (CAMEL_SERVICE (source), FALSE);
* camel_object_unref (CAMEL_OBJECT (source));
*} else
*/
name = input->source_url;
if (gerund)
return g_strdup_printf (_("Fetching email from %s"), name);
else
return g_strdup_printf (_("Fetch email from %s"), name);
}
static void
setup_fetch_mail (gpointer in_data, gpointer op_data, CamelException *ex)
{
fetch_mail_input_t *input = (fetch_mail_input_t *) in_data;
fetch_mail_data_t *data = (fetch_mail_data_t *) op_data;
if (!input->source_url) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
_("You have no remote mail source configured "
"to fetch mail from."));
return;
}
if (input->destination == NULL)
return;
if (!CAMEL_IS_FOLDER (input->destination)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
_("Bad folder passed to fetch_mail"));
return;
}
data->empty = FALSE;
camel_object_ref (CAMEL_OBJECT (input->destination));
}
static void
do_fetch_mail (gpointer in_data, gpointer op_data, CamelException *ex)
{
fetch_mail_input_t *input = (fetch_mail_input_t *) in_data;
fetch_mail_data_t *data = (fetch_mail_data_t *) op_data;
CamelFolder *folder = NULL;
/* If using IMAP, don't do anything... */
if (!strncmp (input->source_url, "imap:", 5)) {
data->empty = FALSE;
return;
}
if (input->destination == NULL) {
input->destination = mail_tool_get_local_inbox (ex);
if (input->destination == NULL)
return;
}
if (!strncmp (input->source_url, "mbox:", 5))
folder = mail_tool_do_movemail (input->source_url, ex);
else
folder = mail_tool_get_inbox (input->source_url, ex);
if (folder == NULL) {
/* This happens with an IMAP source and on error
* and on "no new mail"
*/
camel_object_unref (CAMEL_OBJECT (input->destination));
input->destination = NULL;
data->empty = TRUE;
return;
}
mail_tool_camel_lock_up ();
if (camel_folder_get_message_count (folder) == 0) {
data->empty = TRUE;
} else {
CamelUIDCache *cache = NULL;
gchar *userrules;
gchar *systemrules;
FilterContext *fc;
FilterDriver *filter;
GPtrArray *uids, *new_uids;
char *url, *p, *filename;
int i;
userrules = g_strdup_printf ("%s/filters.xml", evolution_dir);
systemrules = g_strdup_printf ("%s/evolution/filtertypes.xml", EVOLUTION_DATADIR);
fc = filter_context_new ();
rule_context_load ((RuleContext *)fc, systemrules, userrules, NULL, NULL);
g_free (userrules);
g_free (systemrules);
filter = filter_driver_new (fc, mail_tool_filter_get_folder_func, 0);
if (input->hook_func)
camel_object_hook_event (CAMEL_OBJECT (input->destination), "folder_changed",
input->hook_func, input->hook_data);
camel_folder_freeze (input->destination);
uids = camel_folder_get_uids (folder);
if (!input->keep_on_server) {
/* get the mail source's uid cache file */
url = camel_url_to_string (CAMEL_SERVICE (folder->parent_store)->url, FALSE);
for (p = url; *p; p++) {
if (!isascii ((unsigned char)*p) || strchr (" /'\"`&();|<>${}!", *p))
*p = '_';
}
filename = g_strdup_printf ("%s/config/cache-%s", evolution_dir, url);
g_free (url);
cache = camel_uid_cache_new (filename);
if (cache) {
/* determine the new uids */
new_uids = camel_uid_cache_get_new_uids (cache, uids);
camel_folder_free_uids (folder, uids);
uids = new_uids;
}
}
/* get/filter the new messages */
for (i = 0; i < uids->len; i++) {
CamelMimeMessage *message;
CamelMessageInfo *info;
gboolean free_info;
mail_op_set_message ("Retrieving message %d of %d", i + 1, uids->len);
message = camel_folder_get_message (folder, uids->pdata[i], ex);
if (camel_exception_is_set (ex))
continue;
if (camel_folder_has_summary_capability (folder)) {
info = (CamelMessageInfo *) camel_folder_get_message_info (folder, uids->pdata[i]);
free_info = FALSE;
} else {
info = g_new0 (CamelMessageInfo, 1);
free_info = TRUE;
}
filter_driver_run (filter, message, info, input->destination,
FILTER_SOURCE_INCOMING, ex);
if (free_info)
camel_message_info_free (info);
/* we don't care if it was filtered or not here because no matter
what it's been copied to at least 1 folder - even if it's just
the default (assuming we didn't get an exception) */
if (!input->keep_on_server && !camel_exception_is_set (ex)) {
guint32 flags;
flags = camel_folder_get_message_flags (folder, uids->pdata[i]);
camel_folder_set_message_flags (folder, uids->pdata[i],
CAMEL_MESSAGE_DELETED,
~flags);
}
camel_object_unref (CAMEL_OBJECT (message));
}
gtk_object_unref (GTK_OBJECT (filter));
camel_folder_sync (folder, FALSE, ex);
camel_folder_thaw (input->destination);
if (input->hook_func)
camel_object_unhook_event (CAMEL_OBJECT (input->destination), "folder_changed",
input->hook_func, input->hook_data);
if (cache) {
/* save the cache for the next time we fetch mail! */
camel_uid_cache_free_uids (uids);
if (!camel_exception_is_set (ex))
camel_uid_cache_save (cache);
camel_uid_cache_destroy (cache);
} else
camel_folder_free_uids (folder, uids);
data->empty = FALSE;
}
mail_tool_camel_lock_down ();
camel_object_unref (CAMEL_OBJECT (folder));
}
static void
cleanup_fetch_mail (gpointer in_data, gpointer op_data, CamelException *ex)
{
fetch_mail_input_t *input = (fetch_mail_input_t *) in_data;
fetch_mail_data_t *data = (fetch_mail_data_t *) op_data;
if (data->empty && !camel_exception_is_set (ex)) {
GtkWidget *dialog;
gchar *str;
str = g_strdup_printf (_("There is no new mail at %s."),
input->source_url);
dialog = gnome_ok_dialog (str);
g_free (str);
gnome_dialog_run_and_close (GNOME_DIALOG (dialog));
}
g_free (input->source_url);
if (input->destination)
camel_object_unref (CAMEL_OBJECT (input->destination));
}
static const mail_operation_spec op_fetch_mail = {
describe_fetch_mail,
sizeof (fetch_mail_data_t),
setup_fetch_mail,
do_fetch_mail,
cleanup_fetch_mail
};
void
mail_do_fetch_mail (const gchar *source_url, gboolean keep_on_server,
CamelFolder *destination,
gpointer hook_func, gpointer hook_data)
{
fetch_mail_input_t *input;
input = g_new (fetch_mail_input_t, 1);
input->source_url = g_strdup (source_url);
input->keep_on_server = keep_on_server;
input->destination = destination;
input->hook_func = hook_func;
input->hook_data = hook_data;
mail_operation_queue (&op_fetch_mail, input, TRUE);
}
/* ** FILTER ON DEMAND ********************************************************** */
typedef struct filter_ondemand_input_s
{
FilterContext *context;
CamelFolder *source;
CamelFolder *destination;
} filter_ondemand_input_t;
typedef struct filter_ondemand_data_s {
gboolean empty;
} filter_ondemand_data_t;
static gchar *describe_filter_ondemand (gpointer in_data, gboolean gerund);
static void setup_filter_ondemand (gpointer in_data, gpointer op_data,
CamelException *ex);
static void do_filter_ondemand (gpointer in_data, gpointer op_data,
CamelException *ex);
static void cleanup_filter_ondemand (gpointer in_data, gpointer op_data,
CamelException *ex);
static gchar *
describe_filter_ondemand (gpointer in_data, gboolean gerund)
{
/*filter_ondemand_input_t *input = (filter_ondemand_input_t *) in_data;*/
if (gerund)
return g_strdup_printf (_("Filtering email on demand"));
else
return g_strdup_printf (_("Filter email on demand"));
}
static void
setup_filter_ondemand (gpointer in_data, gpointer op_data, CamelException *ex)
{
filter_ondemand_input_t *input = (filter_ondemand_input_t *) in_data;
filter_ondemand_data_t *data = (filter_ondemand_data_t *) op_data;
if (!IS_FILTER_CONTEXT (input->context)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
_("Bad filter context specified"));
return;
}
if (input->source == NULL)
return;
if (!CAMEL_IS_FOLDER (input->source)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
_("Bad input source defined for filtering"));
return;
}
if (input->destination == NULL)
return;
if (!CAMEL_IS_FOLDER (input->destination)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
_("Bad default destination folder"));
return;
}
data->empty = FALSE;
gtk_object_ref (GTK_OBJECT (input->context));
camel_object_ref (CAMEL_OBJECT (input->source));
camel_object_ref (CAMEL_OBJECT (input->destination));
}
static void
do_filter_ondemand (gpointer in_data, gpointer op_data, CamelException *ex)
{
filter_ondemand_input_t *input = (filter_ondemand_input_t *) in_data;
filter_ondemand_data_t *data = (filter_ondemand_data_t *) op_data;
mail_tool_camel_lock_up ();
if (camel_folder_get_message_count (input->source) == 0) {
data->empty = TRUE;
} else {
FilterDriver *driver;
GPtrArray *uids;
int i;
uids = camel_folder_get_uids (input->source);
camel_folder_freeze (input->source);
driver = filter_driver_new (input->context, mail_tool_filter_get_folder_func, NULL);
for (i = 0; i < uids->len; i++) {
CamelMimeMessage *message;
CamelMessageInfo *info;
gboolean filtered;
gboolean free_info;
message = camel_folder_get_message (input->source, uids->pdata[i], ex);
if (camel_exception_is_set (ex))
continue;
if (camel_folder_has_summary_capability (input->source)) {
info = (CamelMessageInfo *) camel_folder_get_message_info (input->source, uids->pdata[i]);
free_info = FALSE;
} else {
info = g_new0 (CamelMessageInfo, 1);
free_info = TRUE;
}
filtered = filter_driver_run (driver, message, info, NULL,
FILTER_SOURCE_DEMAND, ex);
if (free_info)
camel_message_info_free (info);
if (filtered && !camel_exception_is_set (ex)) {
/* we can delete this since it's been filtered */
guint32 flags;
flags = camel_folder_get_message_flags (input->source, uids->pdata[i]);
camel_folder_set_message_flags (input->source, uids->pdata[i],
CAMEL_MESSAGE_DELETED,
~flags);
}
camel_object_unref (CAMEL_OBJECT (message));
}
gtk_object_unref (GTK_OBJECT (driver));
/* FIXME: when we hide deleted msgs, we may want to not expunge? */
camel_folder_sync (input->source, TRUE, ex);
camel_folder_thaw (input->source);
camel_folder_free_uids (input->source, uids);
data->empty = FALSE;
}
mail_tool_camel_lock_down ();
}
static void
cleanup_filter_ondemand (gpointer in_data, gpointer op_data, CamelException *ex)
{
filter_ondemand_input_t *input = (filter_ondemand_input_t *) in_data;
/*filter_ondemand_data_t *data = (filter_ondemand_data_t *) op_data;*/
if (input->source)
camel_object_unref (CAMEL_OBJECT (input->source));
if (input->destination)
camel_object_unref (CAMEL_OBJECT (input->destination));
if (input->context)
gtk_object_unref (GTK_OBJECT (input->context));
}
static const mail_operation_spec op_filter_ondemand = {
describe_filter_ondemand,
sizeof (filter_ondemand_data_t),
setup_filter_ondemand,
do_filter_ondemand,
cleanup_filter_ondemand
};
void
mail_do_filter_ondemand (FilterContext *context, CamelFolder *source, CamelFolder *destination)
{
filter_ondemand_input_t *input;
input = g_new (filter_ondemand_input_t, 1);
input->context = context;
input->source = source;
input->destination = destination;
mail_operation_queue (&op_filter_ondemand, input, TRUE);
}
/* ** SEND MAIL *********************************************************** */
typedef struct send_mail_input_s
{
gchar *xport_uri;
CamelMimeMessage *message;
/* If done_folder != NULL, will add done_flags to
* the flags of the message done_uid in done_folder. */
CamelFolder *done_folder;
char *done_uid;
guint32 done_flags;
GtkWidget *composer;
}
send_mail_input_t;
static gchar *describe_send_mail (gpointer in_data, gboolean gerund);
static void setup_send_mail (gpointer in_data, gpointer op_data,
CamelException *ex);
static void do_send_mail (gpointer in_data, gpointer op_data,
CamelException *ex);
static void cleanup_send_mail (gpointer in_data, gpointer op_data,
CamelException *ex);
static gchar *
describe_send_mail (gpointer in_data, gboolean gerund)
{
send_mail_input_t *input = (send_mail_input_t *) in_data;
if (gerund) {
if (input->message->subject && input->message->subject[0])
return g_strdup_printf (_("Sending \"%s\""),
input->message->subject);
else
return
g_strdup
(_("Sending a message without a subject"));
} else {
if (input->message->subject && input->message->subject[0])
return g_strdup_printf (_("Send \"%s\""),
input->message->subject);
else
return g_strdup (_("Send a message without a subject"));
}
}
static void
setup_send_mail (gpointer in_data, gpointer op_data, CamelException *ex)
{
send_mail_input_t *input = (send_mail_input_t *) in_data;
if (!input->xport_uri) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
/* doesn't really need i18n */
"No transport URI specified for send_mail operation.");
return;
}
if (!CAMEL_IS_MIME_MESSAGE (input->message)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No message specified for send_mail operation.");
return;
}
/* NOTE THE EARLY EXIT!! */
if (input->done_folder == NULL) {
camel_object_ref (CAMEL_OBJECT (input->message));
if (input->composer) {
gtk_object_ref (GTK_OBJECT (input->composer));
gtk_widget_hide (GTK_WIDGET (input->composer));
}
return;
}
if (!CAMEL_IS_FOLDER (input->done_folder)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"Bad done_folder specified for send_mail operation.");
return;
}
if (input->done_uid == NULL) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No done_uid specified for send_mail operation.");
return;
}
camel_object_ref (CAMEL_OBJECT (input->message));
camel_object_ref (CAMEL_OBJECT (input->done_folder));
if (input->composer) {
gtk_object_ref (GTK_OBJECT (input->composer));
gtk_widget_hide (GTK_WIDGET (input->composer));
}
}
static void
do_send_mail (gpointer in_data, gpointer op_data, CamelException *ex)
{
send_mail_input_t *input = (send_mail_input_t *) in_data;
extern CamelFolder *sent_folder;
CamelTransport *xport;
char *x_mailer;
mail_tool_camel_lock_up ();
x_mailer = g_strdup_printf ("Evolution %s (Developer Preview)",
VERSION);
camel_medium_add_header (CAMEL_MEDIUM (input->message), "X-Mailer",
x_mailer);
g_free (x_mailer);
camel_mime_message_set_date (input->message,
CAMEL_MESSAGE_DATE_CURRENT, 0);
xport = camel_session_get_transport (session, input->xport_uri, ex);
mail_tool_camel_lock_down ();
if (camel_exception_is_set (ex))
return;
mail_tool_send_via_transport (xport, CAMEL_MEDIUM (input->message), ex);
camel_object_unref (CAMEL_OBJECT (xport));
if (camel_exception_is_set (ex))
return;
/* if we replied to a message, mark the appropriate flags and stuff */
if (input->done_folder) {
guint32 set;
mail_tool_camel_lock_up ();
set = camel_folder_get_message_flags (input->done_folder,
input->done_uid);
camel_folder_set_message_flags (input->done_folder,
input->done_uid,
input->done_flags,
input->done_flags);
mail_tool_camel_lock_down ();
}
/* now to save the message in Sent */
if (sent_folder) {
CamelMessageInfo *info;
mail_tool_camel_lock_up ();
info = g_new0 (CamelMessageInfo, 1);
info->flags = 0;
camel_folder_append_message (sent_folder, input->message, info, ex);
g_free (info);
mail_tool_camel_lock_down ();
}
}
static void
cleanup_send_mail (gpointer in_data, gpointer op_data, CamelException *ex)
{
send_mail_input_t *input = (send_mail_input_t *) in_data;
camel_object_unref (CAMEL_OBJECT (input->message));
if (input->done_folder)
camel_object_unref (CAMEL_OBJECT (input->done_folder));
g_free (input->xport_uri);
g_free (input->done_uid);
if (input->composer) {
if (!camel_exception_is_set (ex))
gtk_widget_destroy (input->composer);
else
gtk_widget_show (input->composer);
}
}
static const mail_operation_spec op_send_mail = {
describe_send_mail,
0,
setup_send_mail,
do_send_mail,
cleanup_send_mail
};
void
mail_do_send_mail (const char *xport_uri,
CamelMimeMessage *message,
CamelFolder *done_folder,
const char *done_uid,
guint32 done_flags, GtkWidget *composer)
{
send_mail_input_t *input;
input = g_new (send_mail_input_t, 1);
input->xport_uri = g_strdup (xport_uri);
input->message = message;
input->done_folder = done_folder;
input->done_uid = g_strdup (done_uid);
input->done_flags = done_flags;
input->composer = composer;
mail_operation_queue (&op_send_mail, input, TRUE);
}
/* ** SEND MAIL QUEUE ***************************************************** */
typedef struct send_queue_input_s
{
CamelFolder *folder_queue;
gchar *xport_uri;
}
send_queue_input_t;
static gchar *describe_send_queue (gpointer in_data, gboolean gerund);
static void setup_send_queue (gpointer in_data, gpointer op_data,
CamelException *ex);
static void do_send_queue (gpointer in_data, gpointer op_data,
CamelException *ex);
static void cleanup_send_queue (gpointer in_data, gpointer op_data,
CamelException *ex);
static gchar *
describe_send_queue (gpointer in_data, gboolean gerund)
{
/*send_queue_input_t *input = (send_queue_input_t *) in_data;*/
if (gerund) {
return g_strdup_printf (_("Sending queue"));
} else {
return g_strdup_printf (_("Send queue"));
}
}
static void
setup_send_queue (gpointer in_data, gpointer op_data, CamelException *ex)
{
send_queue_input_t *input = (send_queue_input_t *) in_data;
if (!input->xport_uri) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
/* doesn't really need i18n */
"No transport URI specified for send_queue operation.");
return;
}
if (!CAMEL_IS_FOLDER (input->folder_queue)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No queue specified for send_queue operation.");
return;
}
camel_object_ref (CAMEL_OBJECT (input->folder_queue));
}
static void
do_send_queue (gpointer in_data, gpointer op_data, CamelException *ex)
{
send_queue_input_t *input = (send_queue_input_t *) in_data;
extern CamelFolder *sent_folder;
CamelTransport *xport;
GPtrArray *uids;
char *x_mailer;
guint32 set;
int i;
uids = camel_folder_get_uids (input->folder_queue);
if (!uids)
return;
x_mailer = g_strdup_printf ("Evolution %s (Developer Preview)",
VERSION);
for (i = 0; i < uids->len; i++) {
CamelMimeMessage *message;
mail_tool_camel_lock_up ();
message = camel_folder_get_message (input->folder_queue, uids->pdata[i], ex);
if (camel_exception_is_set (ex))
break;
camel_medium_add_header (CAMEL_MEDIUM (message), "X-Mailer", x_mailer);
camel_mime_message_set_date (message, CAMEL_MESSAGE_DATE_CURRENT, 0);
xport = camel_session_get_transport (session, input->xport_uri, ex);
mail_tool_camel_lock_down ();
if (camel_exception_is_set (ex))
break;
mail_tool_send_via_transport (xport, CAMEL_MEDIUM (message), ex);
camel_object_unref (CAMEL_OBJECT (xport));
if (camel_exception_is_set (ex))
break;
mail_tool_camel_lock_up ();
set = camel_folder_get_message_flags (input->folder_queue,
uids->pdata[i]);
camel_folder_set_message_flags (input->folder_queue,
uids->pdata[i],
CAMEL_MESSAGE_DELETED, ~set);
mail_tool_camel_lock_down ();
/* now to save the message in Sent */
if (sent_folder) {
CamelMessageInfo *info;
mail_tool_camel_lock_up ();
info = g_new0 (CamelMessageInfo, 1);
info->flags = 0;
camel_folder_append_message (sent_folder, message, info, ex);
g_free (info);
mail_tool_camel_lock_down ();
}
}
g_free (x_mailer);
for (i = 0; i < uids->len; i++)
g_free (uids->pdata[i]);
g_ptr_array_free (uids, TRUE);
}
static void
cleanup_send_queue (gpointer in_data, gpointer op_data, CamelException *ex)
{
send_queue_input_t *input = (send_queue_input_t *) in_data;
camel_object_unref (CAMEL_OBJECT (input->folder_queue));
g_free (input->xport_uri);
}
static const mail_operation_spec op_send_queue = {
describe_send_queue,
0,
setup_send_queue,
do_send_queue,
cleanup_send_queue
};
void
mail_do_send_queue (CamelFolder *folder_queue,
const char *xport_uri)
{
send_queue_input_t *input;
input = g_new (send_queue_input_t, 1);
input->xport_uri = g_strdup (xport_uri);
input->folder_queue = folder_queue;
mail_operation_queue (&op_send_queue, input, TRUE);
}
/* ** APPEND MESSAGE TO FOLDER ******************************************** */
typedef struct append_mail_input_s
{
CamelFolder *folder;
CamelMimeMessage *message;
CamelMessageInfo *info;
}
append_mail_input_t;
static gchar *describe_append_mail (gpointer in_data, gboolean gerund);
static void setup_append_mail (gpointer in_data, gpointer op_data,
CamelException *ex);
static void do_append_mail (gpointer in_data, gpointer op_data,
CamelException *ex);
static void cleanup_append_mail (gpointer in_data, gpointer op_data,
CamelException *ex);
static gchar *
describe_append_mail (gpointer in_data, gboolean gerund)
{
append_mail_input_t *input = (append_mail_input_t *) in_data;
if (gerund) {
if (input->message->subject && input->message->subject[0])
return g_strdup_printf (_("Appending \"%s\""),
input->message->subject);
else
return
g_strdup (_("Appending a message without a subject"));
} else {
if (input->message->subject && input->message->subject[0])
return g_strdup_printf (_("Appending \"%s\""),
input->message->subject);
else
return g_strdup (_("Appending a message without a subject"));
}
}
static void
setup_append_mail (gpointer in_data, gpointer op_data, CamelException *ex)
{
append_mail_input_t *input = (append_mail_input_t *) in_data;
if (!CAMEL_IS_MIME_MESSAGE (input->message)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No message specified for append_mail operation.");
return;
}
if (!CAMEL_IS_FOLDER (input->folder)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"Bad done_folder specified for append_mail operation.");
return;
}
camel_object_ref (CAMEL_OBJECT (input->message));
camel_object_ref (CAMEL_OBJECT (input->folder));
}
static void
do_append_mail (gpointer in_data, gpointer op_data, CamelException *ex)
{
append_mail_input_t *input = (append_mail_input_t *) in_data;
camel_mime_message_set_date (input->message,
CAMEL_MESSAGE_DATE_CURRENT, 0);
mail_tool_camel_lock_up ();
/* now to save the message in the specified folder */
camel_folder_append_message (input->folder, input->message, input->info, ex);
mail_tool_camel_lock_down ();
}
static void
cleanup_append_mail (gpointer in_data, gpointer op_data, CamelException *ex)
{
append_mail_input_t *input = (append_mail_input_t *) in_data;
camel_object_unref (CAMEL_OBJECT (input->message));
camel_object_unref (CAMEL_OBJECT (input->folder));
}
static const mail_operation_spec op_append_mail = {
describe_append_mail,
0,
setup_append_mail,
do_append_mail,
cleanup_append_mail
};
void
mail_do_append_mail (CamelFolder *folder,
CamelMimeMessage *message,
CamelMessageInfo *info)
{
append_mail_input_t *input;
input = g_new (append_mail_input_t, 1);
input->folder = folder;
input->message = message;
input->info = info;
mail_operation_queue (&op_append_mail, input, TRUE);
}
/* ** EXPUNGE FOLDER ****************************************************** */
static gchar *describe_expunge_folder (gpointer in_data, gboolean gerund);
static void setup_expunge_folder (gpointer in_data, gpointer op_data,
CamelException *ex);
static void do_expunge_folder (gpointer in_data, gpointer op_data,
CamelException *ex);
static void cleanup_expunge_folder (gpointer in_data, gpointer op_data,
CamelException *ex);
static gchar *
describe_expunge_folder (gpointer in_data, gboolean gerund)
{
CamelFolder *f = CAMEL_FOLDER (in_data);
if (gerund)
return g_strdup_printf (_("Expunging \"%s\""), mail_tool_get_folder_name (f));
else
return g_strdup_printf (_("Expunge \"%s\""), mail_tool_get_folder_name (f));
}
static void
setup_expunge_folder (gpointer in_data, gpointer op_data, CamelException *ex)
{
if (!CAMEL_IS_FOLDER (in_data)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
/* doesn't need i18n */
"No folder is selected to be expunged");
return;
}
camel_object_ref (CAMEL_OBJECT (in_data));
}
static void
do_expunge_folder (gpointer in_data, gpointer op_data, CamelException *ex)
{
mail_tool_camel_lock_up ();
camel_folder_expunge (CAMEL_FOLDER (in_data), ex);
mail_tool_camel_lock_down ();
}
static void
cleanup_expunge_folder (gpointer in_data, gpointer op_data,
CamelException *ex)
{
camel_object_unref (CAMEL_OBJECT (in_data));
}
static const mail_operation_spec op_expunge_folder = {
describe_expunge_folder,
0,
setup_expunge_folder,
do_expunge_folder,
cleanup_expunge_folder
};
void
mail_do_expunge_folder (CamelFolder *folder)
{
mail_operation_queue (&op_expunge_folder, folder, FALSE);
}
/* ** TRANSFER MESSAGES **************************************************** */
typedef struct transfer_messages_input_s
{
CamelFolder *source;
GPtrArray *uids;
gboolean delete_from_source;
gchar *dest_uri;
}
transfer_messages_input_t;
static gchar *describe_transfer_messages (gpointer in_data, gboolean gerund);
static void setup_transfer_messages (gpointer in_data, gpointer op_data,
CamelException *ex);
static void do_transfer_messages (gpointer in_data, gpointer op_data,
CamelException *ex);
static void cleanup_transfer_messages (gpointer in_data, gpointer op_data,
CamelException *ex);
static gchar *
describe_transfer_messages (gpointer in_data, gboolean gerund)
{
transfer_messages_input_t *input = (transfer_messages_input_t *) in_data;
char *format;
if (gerund) {
if (input->delete_from_source)
format = _("Moving messages from \"%s\" into \"%s\"");
else
format = _("Copying messages from \"%s\" into \"%s\"");
} else {
if (input->delete_from_source)
format = _("Move messages from \"%s\" into \"%s\"");
else
format = _("Copy messages from \"%s\" into \"%s\"");
}
return g_strdup_printf (format,
mail_tool_get_folder_name (input->source),
input->dest_uri);
}
static void
setup_transfer_messages (gpointer in_data, gpointer op_data,
CamelException *ex)
{
transfer_messages_input_t *input = (transfer_messages_input_t *) in_data;
char *verb;
if (input->delete_from_source)
/* don't need i18n */
verb = "move";
else
verb = "copy";
if (!CAMEL_IS_FOLDER (input->source)) {
camel_exception_setv (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No source folder to %s messages from specified.",
verb);
return;
}
if (input->uids == NULL) {
camel_exception_setv (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No messages to %s have been specified.",
verb);
return;
}
if (input->dest_uri == NULL) {
camel_exception_setv (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No URI to %s to has been specified.",
verb);
return;
}
camel_object_ref (CAMEL_OBJECT (input->source));
}
static void
do_transfer_messages (gpointer in_data, gpointer op_data, CamelException *ex)
{
transfer_messages_input_t *input = (transfer_messages_input_t *) in_data;
CamelFolder *dest;
gint i;
gchar *desc;
void (*func) (CamelFolder *, const char *,
CamelFolder *,
CamelException *);
if (input->delete_from_source) {
func = camel_folder_move_message_to;
desc = _("Moving");
} else {
func = camel_folder_copy_message_to;
desc = _("Copying");
}
dest = mail_tool_uri_to_folder (input->dest_uri, ex);
if (camel_exception_is_set (ex))
return;
mail_tool_camel_lock_up ();
camel_folder_freeze (input->source);
camel_folder_freeze (dest);
for (i = 0; i < input->uids->len; i++) {
mail_op_set_message (_("%s message %d of %d (uid \"%s\")"), desc,
i + 1, input->uids->len, (char *) input->uids->pdata[i]);
(func) (input->source,
input->uids->pdata[i], dest,
ex);
g_free (input->uids->pdata[i]);
if (camel_exception_is_set (ex))
break;
}
camel_folder_thaw (input->source);
camel_folder_thaw (dest);
camel_object_unref (CAMEL_OBJECT (dest));
mail_tool_camel_lock_down ();
}
static void
cleanup_transfer_messages (gpointer in_data, gpointer op_data,
CamelException *ex)
{
transfer_messages_input_t *input = (transfer_messages_input_t *) in_data;
camel_object_unref (CAMEL_OBJECT (input->source));
g_free (input->dest_uri);
g_ptr_array_free (input->uids, TRUE);
}
static const mail_operation_spec op_transfer_messages = {
describe_transfer_messages,
0,
setup_transfer_messages,
do_transfer_messages,
cleanup_transfer_messages
};
void
mail_do_transfer_messages (CamelFolder *source, GPtrArray *uids,
gboolean delete_from_source,
gchar *dest_uri)
{
transfer_messages_input_t *input;
input = g_new (transfer_messages_input_t, 1);
input->source = source;
input->uids = uids;
input->delete_from_source = delete_from_source;
input->dest_uri = g_strdup (dest_uri);
mail_operation_queue (&op_transfer_messages, input, TRUE);
}
/* ** FLAG MESSAGES ******************************************************* */
typedef struct flag_messages_input_s
{
CamelFolder *source;
GPtrArray *uids;
gboolean invert;
guint32 mask;
guint32 set;
gboolean flag_all;
}
flag_messages_input_t;
static gchar *describe_flag_messages (gpointer in_data, gboolean gerund);
static void setup_flag_messages (gpointer in_data, gpointer op_data,
CamelException *ex);
static void do_flag_messages (gpointer in_data, gpointer op_data,
CamelException *ex);
static void cleanup_flag_messages (gpointer in_data, gpointer op_data,
CamelException *ex);
static gchar *
describe_flag_messages (gpointer in_data, gboolean gerund)
{
flag_messages_input_t *input = (flag_messages_input_t *) in_data;
/* FIXME: change based on flags being applied? */
if (gerund)
return g_strdup_printf (_("Marking messages in folder \"%s\""),
mail_tool_get_folder_name (input->source));
else
return g_strdup_printf (_("Mark messages in folder \"%s\""),
mail_tool_get_folder_name (input->source));
}
static void
setup_flag_messages (gpointer in_data, gpointer op_data, CamelException *ex)
{
flag_messages_input_t *input = (flag_messages_input_t *) in_data;
if (!CAMEL_IS_FOLDER (input->source)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
/* doesn't need i18n */
"No source folder to flag messages from specified.");
return;
}
if (!input->flag_all && input->uids == NULL) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No messages to flag have been specified.");
return;
}
camel_object_ref (CAMEL_OBJECT (input->source));
}
static void
do_flag_messages (gpointer in_data, gpointer op_data, CamelException *ex)
{
flag_messages_input_t *input = (flag_messages_input_t *) in_data;
gint i;
mail_tool_camel_lock_up ();
camel_folder_freeze (input->source);
if (input->uids == NULL)
input->uids = camel_folder_get_uids (input->source);
mail_tool_camel_lock_down ();
for (i = 0; i < input->uids->len; i++) {
mail_op_set_message ("Marking message %d of %d", i + 1,
input->uids->len);
if (input->invert) {
const CamelMessageInfo *info;
mail_tool_camel_lock_up ();
info = camel_folder_get_message_info (input->source, input->uids->pdata[i]);
camel_folder_set_message_flags (input->source, input->uids->pdata[i],
input->mask, ~info->flags);
mail_tool_camel_lock_down ();
} else {
mail_tool_set_uid_flags (input->source, input->uids->pdata[i],
input->mask, input->set);
}
if (input->flag_all == FALSE)
g_free (input->uids->pdata[i]);
}
mail_tool_camel_lock_up ();
if (input->flag_all) {
camel_folder_free_uids (input->source, input->uids);
input->uids = NULL;
}
camel_folder_thaw (input->source);
mail_tool_camel_lock_down ();
}
static void
cleanup_flag_messages (gpointer in_data, gpointer op_data,
CamelException *ex)
{
flag_messages_input_t *input = (flag_messages_input_t *) in_data;
camel_object_unref (CAMEL_OBJECT (input->source));
if (input->uids)
g_ptr_array_free (input->uids, TRUE);
}
static const mail_operation_spec op_flag_messages = {
describe_flag_messages,
0,
setup_flag_messages,
do_flag_messages,
cleanup_flag_messages
};
void
mail_do_flag_messages (CamelFolder *source, GPtrArray *uids,
gboolean invert,
guint32 mask, guint32 set)
{
flag_messages_input_t *input;
input = g_new (flag_messages_input_t, 1);
input->source = source;
input->uids = uids;
input->invert = invert;
input->mask = mask;
input->set = set;
input->flag_all = FALSE;
mail_operation_queue (&op_flag_messages, input, TRUE);
}
void
mail_do_flag_all_messages (CamelFolder *source, gboolean invert,
guint32 mask, guint32 set)
{
flag_messages_input_t *input;
input = g_new (flag_messages_input_t, 1);
input->source = source;
input->uids = NULL;
input->invert = invert;
input->mask = mask;
input->set = set;
input->flag_all = TRUE;
mail_operation_queue (&op_flag_messages, input, TRUE);
}
/* ** SCAN SUBFOLDERS ***************************************************** */
typedef struct scan_subfolders_input_s
{
gchar *source_uri;
gboolean add_INBOX;
EvolutionStorage *storage;
}
scan_subfolders_input_t;
typedef struct scan_subfolders_folderinfo_s
{
char *path;
char *uri;
}
scan_subfolders_folderinfo_t;
typedef struct scan_subfolders_op_s
{
GPtrArray *new_folders;
}
scan_subfolders_op_t;
static gchar *describe_scan_subfolders (gpointer in_data, gboolean gerund);
static void setup_scan_subfolders (gpointer in_data, gpointer op_data,
CamelException *ex);
static void do_scan_subfolders (gpointer in_data, gpointer op_data,
CamelException *ex);
static void cleanup_scan_subfolders (gpointer in_data, gpointer op_data,
CamelException *ex);
static gchar *
describe_scan_subfolders (gpointer in_data, gboolean gerund)
{
scan_subfolders_input_t *input = (scan_subfolders_input_t *) in_data;
if (gerund)
return g_strdup_printf (_("Scanning folders in \"%s\""),
input->source_uri);
else
return g_strdup_printf (_("Scan folders in \"%s\""),
input->source_uri);
}
static void
setup_scan_subfolders (gpointer in_data, gpointer op_data,
CamelException *ex)
{
scan_subfolders_input_t *input = (scan_subfolders_input_t *) in_data;
scan_subfolders_op_t *data = (scan_subfolders_op_t *) op_data;
if (!input->source_uri) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
/* doesn't need i18n */
"No source uri to scan subfolders from was provided.");
return;
}
if (!EVOLUTION_IS_STORAGE (input->storage)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No storage to scan subfolders into was provided.");
return;
}
gtk_object_ref (GTK_OBJECT (input->storage));
data->new_folders = g_ptr_array_new ();
}
static void
do_scan_subfolders (gpointer in_data, gpointer op_data, CamelException *ex)
{
scan_subfolders_input_t *input = (scan_subfolders_input_t *) in_data;
scan_subfolders_op_t *data = (scan_subfolders_op_t *) op_data;
scan_subfolders_folderinfo_t *info;
GPtrArray *lsub;
CamelFolder *folder;
int i;
char *splice;
if (input->source_uri[strlen (input->source_uri) - 1] == '/')
splice = "";
else
splice = "/";
folder = mail_tool_get_root_of_store (input->source_uri, ex);
if (camel_exception_is_set (ex))
return;
mail_tool_camel_lock_up ();
lsub = camel_folder_get_subfolder_names (folder);
mail_tool_camel_lock_down ();
for (i = 0; i < lsub->len; i++) {
mail_op_set_message (_("Found subfolder \"%s\""), (char *) lsub->pdata[i]);
info = g_new (scan_subfolders_folderinfo_t, 1);
info->path = g_strdup_printf ("/%s", (char *) lsub->pdata[i]);
info->uri = g_strdup_printf ("%s%s%s", input->source_uri, splice,
(char *)lsub->pdata[i]);
g_ptr_array_add (data->new_folders, info);
}
camel_folder_free_subfolder_names (folder, lsub);
/* FIXME: We intentionally lose a reference to the store here
* for the benefit of the IMAP provider. Undo this when the
* namespace situation is fixed.
*/
camel_object_ref (CAMEL_OBJECT (folder->parent_store));
camel_object_unref (CAMEL_OBJECT (folder));
}
static void
cleanup_scan_subfolders (gpointer in_data, gpointer op_data,
CamelException *ex)
{
scan_subfolders_input_t *input = (scan_subfolders_input_t *) in_data;
scan_subfolders_op_t *data = (scan_subfolders_op_t *) op_data;
int i;
for (i = 0; i < data->new_folders->len; i++) {
scan_subfolders_folderinfo_t *info;
info = data->new_folders->pdata[i];
evolution_storage_new_folder (input->storage,
info->path,
g_basename (info->path),
"mail",
info->uri, _("(No description)"));
g_free (info->path);
g_free (info->uri);
g_free (info);
}
g_ptr_array_free (data->new_folders, TRUE);
gtk_object_unref (GTK_OBJECT (input->storage));
g_free (input->source_uri);
}
static const mail_operation_spec op_scan_subfolders = {
describe_scan_subfolders,
sizeof (scan_subfolders_op_t),
setup_scan_subfolders,
do_scan_subfolders,
cleanup_scan_subfolders
};
void
mail_do_scan_subfolders (const gchar *source_uri, EvolutionStorage *storage)
{
scan_subfolders_input_t *input;
input = g_new (scan_subfolders_input_t, 1);
input->source_uri = g_strdup (source_uri);
input->storage = storage;
mail_operation_queue (&op_scan_subfolders, input, TRUE);
}
/* ** ATTACH MESSAGE ****************************************************** */
typedef struct attach_message_input_s
{
EMsgComposer *composer;
CamelFolder *folder;
gchar *uid;
}
attach_message_input_t;
typedef struct attach_message_data_s
{
CamelMimePart *part;
}
attach_message_data_t;
static gchar *describe_attach_message (gpointer in_data, gboolean gerund);
static void setup_attach_message (gpointer in_data, gpointer op_data,
CamelException *ex);
static void do_attach_message (gpointer in_data, gpointer op_data,
CamelException *ex);
static void cleanup_attach_message (gpointer in_data, gpointer op_data,
CamelException *ex);
static gchar *
describe_attach_message (gpointer in_data, gboolean gerund)
{
attach_message_input_t *input = (attach_message_input_t *) in_data;
if (gerund)
return
g_strdup_printf
(_("Attaching messages from folder \"%s\""),
mail_tool_get_folder_name (input->folder));
else
return g_strdup_printf (_("Attach messages from \"%s\""),
mail_tool_get_folder_name (input->folder));
}
static void
setup_attach_message (gpointer in_data, gpointer op_data, CamelException *ex)
{
attach_message_input_t *input = (attach_message_input_t *) in_data;
if (!input->uid) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
/* doesn't need i18n */
"No UID specified to attach.");
return;
}
if (!CAMEL_IS_FOLDER (input->folder)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No folder to fetch the message from specified.");
return;
}
if (!E_IS_MSG_COMPOSER (input->composer)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No message composer from specified.");
return;
}
camel_object_ref (CAMEL_OBJECT (input->folder));
gtk_object_ref (GTK_OBJECT (input->composer));
}
static void
do_attach_message (gpointer in_data, gpointer op_data, CamelException *ex)
{
attach_message_input_t *input = (attach_message_input_t *) in_data;
attach_message_data_t *data = (attach_message_data_t *) op_data;
CamelMimeMessage *message;
CamelMimePart *part;
mail_tool_camel_lock_up ();
message = camel_folder_get_message (input->folder, input->uid, ex);
if (!message) {
mail_tool_camel_lock_down ();
return;
}
part = mail_tool_make_message_attachment (message);
camel_object_unref (CAMEL_OBJECT (message));
mail_tool_camel_lock_down ();
if (!part)
return;
data->part = part;
}
static void
cleanup_attach_message (gpointer in_data, gpointer op_data,
CamelException *ex)
{
attach_message_input_t *input = (attach_message_input_t *) in_data;
attach_message_data_t *data = (attach_message_data_t *) op_data;
e_msg_composer_attach (input->composer, data->part);
camel_object_unref (CAMEL_OBJECT (data->part));
camel_object_unref (CAMEL_OBJECT (input->folder));
gtk_object_unref (GTK_OBJECT (input->composer));
g_free (input->uid);
}
static const mail_operation_spec op_attach_message = {
describe_attach_message,
sizeof (attach_message_data_t),
setup_attach_message,
do_attach_message,
cleanup_attach_message
};
void
mail_do_attach_message (CamelFolder *folder, const char *uid,
EMsgComposer *composer)
{
attach_message_input_t *input;
input = g_new (attach_message_input_t, 1);
input->folder = folder;
input->uid = g_strdup (uid);
input->composer = composer;
mail_operation_queue (&op_attach_message, input, TRUE);
}
/* ** FORWARD MESSAGES **************************************************** */
typedef struct forward_messages_input_s
{
CamelMimeMessage *basis;
CamelFolder *source;
GPtrArray *uids;
EMsgComposer *composer;
}
forward_messages_input_t;
typedef struct forward_messages_data_s
{
gchar *subject;
GPtrArray *parts;
}
forward_messages_data_t;
static gchar *describe_forward_messages (gpointer in_data, gboolean gerund);
static void setup_forward_messages (gpointer in_data, gpointer op_data,
CamelException *ex);
static void do_forward_messages (gpointer in_data, gpointer op_data,
CamelException *ex);
static void cleanup_forward_messages (gpointer in_data, gpointer op_data,
CamelException *ex);
static gchar *
describe_forward_messages (gpointer in_data, gboolean gerund)
{
forward_messages_input_t *input = (forward_messages_input_t *) in_data;
if (gerund) {
if (input->basis->subject)
return g_strdup_printf (_("Forwarding messages \"%s\""),
input->basis->subject);
else
return
g_strdup_printf
(_("Forwarding a message without a subject"));
} else {
if (input->basis->subject)
return g_strdup_printf (_("Forward message \"%s\""),
input->basis->subject);
else
return
g_strdup_printf
(_("Forward a message without a subject"));
}
}
static void
setup_forward_messages (gpointer in_data, gpointer op_data,
CamelException *ex)
{
forward_messages_input_t *input = (forward_messages_input_t *) in_data;
if (!input->uids) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
/* doesn't need i18n */
"No UIDs specified to attach.");
return;
}
if (!CAMEL_IS_MIME_MESSAGE (input->basis)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No basic message to forward was specified.");
return;
}
if (!CAMEL_IS_FOLDER (input->source)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No folder to fetch the messages from specified.");
return;
}
if (!E_IS_MSG_COMPOSER (input->composer)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No message composer from specified.");
return;
}
camel_object_ref (CAMEL_OBJECT (input->basis));
camel_object_ref (CAMEL_OBJECT (input->source));
gtk_object_ref (GTK_OBJECT (input->composer));
}
static void
do_forward_messages (gpointer in_data, gpointer op_data, CamelException *ex)
{
forward_messages_input_t *input = (forward_messages_input_t *) in_data;
forward_messages_data_t *data = (forward_messages_data_t *) op_data;
CamelMimeMessage *message;
CamelMimePart *part;
int i;
data->parts = g_ptr_array_new ();
mail_tool_camel_lock_up ();
for (i = 0; i < input->uids->len; i++) {
mail_op_set_message (_("Retrieving message number %d of %d (uid \"%s\")"),
i + 1, input->uids->len, (char *) input->uids->pdata[i]);
message =
camel_folder_get_message (input->source,
input->uids->pdata[i], ex);
g_free (input->uids->pdata[i]);
if (!message) {
mail_tool_camel_lock_down ();
return;
}
part = mail_tool_make_message_attachment (message);
if (!part) {
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
_("Failed to generate mime part from "
"message while generating forwarded message."));
mail_tool_camel_lock_down ();
return;
}
camel_object_unref (CAMEL_OBJECT (message));
g_ptr_array_add (data->parts, part);
}
mail_tool_camel_lock_down ();
data->subject = mail_tool_generate_forward_subject (input->basis);
}
static void
cleanup_forward_messages (gpointer in_data, gpointer op_data,
CamelException *ex)
{
forward_messages_input_t *input =
(forward_messages_input_t *) in_data;
forward_messages_data_t *data = (forward_messages_data_t *) op_data;
int i;
for (i = 0; i < data->parts->len; i++) {
e_msg_composer_attach (input->composer,
data->parts->pdata[i]);
camel_object_unref (CAMEL_OBJECT (data->parts->pdata[i]));
}
camel_object_unref (CAMEL_OBJECT (input->source));
e_msg_composer_set_headers (input->composer, NULL, NULL, NULL,
data->subject);
gtk_object_unref (GTK_OBJECT (input->composer));
g_free (data->subject);
g_ptr_array_free (data->parts, TRUE);
g_ptr_array_free (input->uids, TRUE);
gtk_widget_show (GTK_WIDGET (input->composer));
}
static const mail_operation_spec op_forward_messages = {
describe_forward_messages,
sizeof (forward_messages_data_t),
setup_forward_messages,
do_forward_messages,
cleanup_forward_messages
};
void
mail_do_forward_message (CamelMimeMessage *basis,
CamelFolder *source,
GPtrArray *uids, EMsgComposer *composer)
{
forward_messages_input_t *input;
input = g_new (forward_messages_input_t, 1);
input->basis = basis;
input->source = source;
input->uids = uids;
input->composer = composer;
mail_operation_queue (&op_forward_messages, input, TRUE);
}
/* ** LOAD FOLDER ********************************************************* */
typedef struct load_folder_input_s
{
FolderBrowser *fb;
gchar *url;
}
load_folder_input_t;
static gchar *describe_load_folder (gpointer in_data, gboolean gerund);
static void setup_load_folder (gpointer in_data, gpointer op_data,
CamelException *ex);
static void do_load_folder (gpointer in_data, gpointer op_data,
CamelException *ex);
static void cleanup_load_folder (gpointer in_data, gpointer op_data,
CamelException *ex);
static gchar *
describe_load_folder (gpointer in_data, gboolean gerund)
{
load_folder_input_t *input = (load_folder_input_t *) in_data;
if (gerund) {
return g_strdup_printf (_("Loading \"%s\""), input->url);
} else {
return g_strdup_printf (_("Load \"%s\""), input->url);
}
}
static void
setup_load_folder (gpointer in_data, gpointer op_data, CamelException *ex)
{
load_folder_input_t *input = (load_folder_input_t *) in_data;
if (!IS_FOLDER_BROWSER (input->fb)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
/* doesn't need i18n */
"No folder browser specified to load into.");
return;
}
if (!input->url) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No URL to load was specified.");
return;
}
gtk_object_ref (GTK_OBJECT (input->fb));
if (input->fb->uri)
g_free (input->fb->uri);
input->fb->uri = input->url;
}
static void
do_load_folder (gpointer in_data, gpointer op_data, CamelException *ex)
{
load_folder_input_t *input = (load_folder_input_t *) in_data;
CamelFolder *folder;
folder = mail_tool_uri_to_folder (input->url, ex);
if (!folder)
return;
if (input->fb->folder) {
mail_tool_camel_lock_up ();
camel_object_unref (CAMEL_OBJECT (input->fb->folder));
mail_tool_camel_lock_down ();
}
input->fb->folder = folder;
}
static void
cleanup_load_folder (gpointer in_data, gpointer op_data, CamelException *ex)
{
load_folder_input_t *input = (load_folder_input_t *) in_data;
if (input->fb->folder) {
gtk_widget_set_sensitive (GTK_WIDGET (input->fb->search_entry),
camel_folder_has_search_capability (input->
fb->
folder));
gtk_widget_set_sensitive (GTK_WIDGET (input->fb->search_menu),
camel_folder_has_search_capability (input->
fb->
folder));
message_list_set_folder (input->fb->message_list, input->fb->folder);
}
/*g_free (input->url); = fb->uri now */
}
static const mail_operation_spec op_load_folder = {
describe_load_folder,
0,
setup_load_folder,
do_load_folder,
cleanup_load_folder
};
void
mail_do_load_folder (FolderBrowser *fb, const char *url)
{
load_folder_input_t *input;
input = g_new (load_folder_input_t, 1);
input->fb = fb;
input->url = g_strdup (url);
mail_operation_queue (&op_load_folder, input, TRUE);
}
/* ** CREATE FOLDER ******************************************************* */
typedef struct create_folder_input_s
{
Evolution_ShellComponentListener listener;
char *uri;
char *type;
}
create_folder_input_t;
typedef struct create_folder_data_s
{
Evolution_ShellComponentListener_Result result;
}
create_folder_data_t;
static gchar *describe_create_folder (gpointer in_data, gboolean gerund);
static void setup_create_folder (gpointer in_data, gpointer op_data,
CamelException *ex);
static void do_create_folder (gpointer in_data, gpointer op_data,
CamelException *ex);
static void cleanup_create_folder (gpointer in_data, gpointer op_data,
CamelException *ex);
static gchar *
describe_create_folder (gpointer in_data, gboolean gerund)
{
create_folder_input_t *input = (create_folder_input_t *) in_data;
if (gerund) {
return g_strdup_printf (_("Creating \"%s\""), input->uri);
} else {
return g_strdup_printf (_("Create \"%s\""), input->uri);
}
}
static void
setup_create_folder (gpointer in_data, gpointer op_data, CamelException *ex)
{
create_folder_input_t *input = (create_folder_input_t *) in_data;
if (input->listener == CORBA_OBJECT_NIL) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
/* doesn't need i18n */
"Invalid listener passed to create_folder");
return;
}
if (input->uri == NULL) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"Invalid url passed to create_folder");
return;
}
if (input->type == NULL) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No type passed to create_folder");
return;
}
}
static void
do_create_folder (gpointer in_data, gpointer op_data, CamelException *ex)
{
create_folder_input_t *input = (create_folder_input_t *) in_data;
create_folder_data_t *data = (create_folder_data_t *) op_data;
CamelFolder *folder;
gchar *camel_url;
if (strcmp (input->type, "mail") != 0)
data->result =
Evolution_ShellComponentListener_UNSUPPORTED_TYPE;
else {
camel_url = g_strdup_printf ("mbox://%s", input->uri);
folder = mail_tool_get_folder_from_urlname (camel_url,
"mbox", TRUE, ex);
g_free (camel_url);
if (!camel_exception_is_set (ex)) {
camel_object_unref (CAMEL_OBJECT (folder));
data->result = Evolution_ShellComponentListener_OK;
} else {
data->result =
Evolution_ShellComponentListener_INVALID_URI;
}
}
}
static void
cleanup_create_folder (gpointer in_data, gpointer op_data,
CamelException *ex)
{
create_folder_input_t *input = (create_folder_input_t *) in_data;
create_folder_data_t *data = (create_folder_data_t *) op_data;
CORBA_Environment ev;
CORBA_exception_init (&ev);
Evolution_ShellComponentListener_report_result (input->listener,
data->result, &ev);
if (ev._major != CORBA_NO_EXCEPTION)
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
_("Exception while reporting result to shell "
"component listener."));
CORBA_Object_release (input->listener, &ev);
g_free (input->uri);
g_free (input->type);
CORBA_exception_free (&ev);
}
static const mail_operation_spec op_create_folder = {
describe_create_folder,
sizeof (create_folder_data_t),
setup_create_folder,
do_create_folder,
cleanup_create_folder
};
void
mail_do_create_folder (const Evolution_ShellComponentListener listener,
const char *uri, const char *type)
{
CORBA_Environment ev;
create_folder_input_t *input;
CORBA_exception_init (&ev);
input = g_new (create_folder_input_t, 1);
input->listener = CORBA_Object_duplicate (listener, &ev);
input->uri = g_strdup (uri);
input->type = g_strdup (type);
CORBA_exception_free (&ev);
mail_operation_queue (&op_create_folder, input, FALSE);
}
/* ** SYNC FOLDER ********************************************************* */
static gchar *describe_sync_folder (gpointer in_data, gboolean gerund);
static void setup_sync_folder (gpointer in_data, gpointer op_data,
CamelException *ex);
static void do_sync_folder (gpointer in_data, gpointer op_data,
CamelException *ex);
static void cleanup_sync_folder (gpointer in_data, gpointer op_data,
CamelException *ex);
static gchar *
describe_sync_folder (gpointer in_data, gboolean gerund)
{
CamelFolder *f = CAMEL_FOLDER (in_data);
if (gerund) {
return g_strdup_printf (_("Synchronizing \"%s\""), mail_tool_get_folder_name (f));
} else {
return g_strdup_printf (_("Synchronize \"%s\""), mail_tool_get_folder_name (f));
}
}
static void
setup_sync_folder (gpointer in_data, gpointer op_data, CamelException *ex)
{
if (!CAMEL_IS_FOLDER (in_data)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
/* doesn't need i18n */
"No folder is selected to be synced");
return;
}
camel_object_ref (CAMEL_OBJECT (in_data));
}
static void
do_sync_folder (gpointer in_data, gpointer op_data, CamelException *ex)
{
mail_tool_camel_lock_up ();
camel_folder_sync (CAMEL_FOLDER (in_data), FALSE, ex);
mail_tool_camel_lock_down ();
}
static void
cleanup_sync_folder (gpointer in_data, gpointer op_data, CamelException *ex)
{
camel_object_unref (CAMEL_OBJECT (in_data));
}
static const mail_operation_spec op_sync_folder = {
describe_sync_folder,
0,
setup_sync_folder,
do_sync_folder,
cleanup_sync_folder
};
void
mail_do_sync_folder (CamelFolder *folder)
{
mail_operation_queue (&op_sync_folder, folder, FALSE);
}
/* ** DISPLAY MESSAGE ***************************************************** */
typedef struct display_message_input_s
{
MessageList *ml;
gchar *uid;
gint (*timeout) (gpointer);
}
display_message_input_t;
typedef struct display_message_data_s
{
CamelMimeMessage *msg;
}
display_message_data_t;
static gchar *describe_display_message (gpointer in_data, gboolean gerund);
static void setup_display_message (gpointer in_data, gpointer op_data,
CamelException *ex);
static void do_display_message (gpointer in_data, gpointer op_data,
CamelException *ex);
static void cleanup_display_message (gpointer in_data, gpointer op_data,
CamelException *ex);
static gchar *
describe_display_message (gpointer in_data, gboolean gerund)
{
display_message_input_t *input = (display_message_input_t *) in_data;
if (gerund) {
if (input->uid)
return g_strdup_printf (_("Displaying message UID \"%s\""),
input->uid);
else
return g_strdup (_("Clearing message display"));
} else {
if (input->uid)
return g_strdup_printf (_("Display message UID \"%s\""),
input->uid);
else
return g_strdup (_("Clear message display"));
}
}
static void
setup_display_message (gpointer in_data, gpointer op_data,
CamelException *ex)
{
display_message_input_t *input = (display_message_input_t *) in_data;
display_message_data_t *data = (display_message_data_t *) op_data;
if (!IS_MESSAGE_LIST (input->ml)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
/* doesn't need i18n */
"Invalid message list passed to display_message");
return;
}
if (!input->timeout) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No timeout callback passed to display_message");
return;
}
data->msg = NULL;
gtk_object_ref (GTK_OBJECT (input->ml));
}
static void
do_display_message (gpointer in_data, gpointer op_data, CamelException *ex)
{
display_message_input_t *input = (display_message_input_t *) in_data;
display_message_data_t *data = (display_message_data_t *) op_data;
if (input->uid == NULL) {
data->msg = NULL;
return;
}
data->msg = camel_folder_get_message (input->ml->folder,
input->uid, ex);
}
static void
cleanup_display_message (gpointer in_data, gpointer op_data,
CamelException *ex)
{
display_message_input_t *input = (display_message_input_t *) in_data;
display_message_data_t *data = (display_message_data_t *) op_data;
MailDisplay *md = input->ml->parent_folder_browser->mail_display;
if (data->msg == NULL) {
mail_display_set_message (md, NULL);
} else {
gint timeout = mail_config_mark_as_seen_timeout ();
if (input->ml->seen_id)
gtk_timeout_remove (input->ml->seen_id);
mail_display_set_message (md, CAMEL_MEDIUM (data->msg));
camel_object_unref (CAMEL_OBJECT (data->msg));
if (timeout > 0) {
input->ml->seen_id = gtk_timeout_add (timeout,
input->timeout,
input->ml);
} else {
input->ml->seen_id = 0;
input->timeout (input->ml);
}
}
if (input->uid)
g_free (input->uid);
gtk_object_unref (GTK_OBJECT (input->ml));
}
static const mail_operation_spec op_display_message = {
describe_display_message,
sizeof (display_message_data_t),
setup_display_message,
do_display_message,
cleanup_display_message
};
void
mail_do_display_message (MessageList *ml, const char *uid,
gint (*timeout) (gpointer))
{
display_message_input_t *input;
input = g_new (display_message_input_t, 1);
input->ml = ml;
input->uid = g_strdup (uid);
input->timeout = timeout;
mail_operation_queue (&op_display_message, input, TRUE);
}
/* ** EDIT MESSAGES ******************************************************* */
typedef struct edit_messages_input_s {
CamelFolder *folder;
GPtrArray *uids;
GtkSignalFunc signal;
} edit_messages_input_t;
typedef struct edit_messages_data_s {
GPtrArray *messages;
} edit_messages_data_t;
static gchar *describe_edit_messages (gpointer in_data, gboolean gerund);
static void setup_edit_messages (gpointer in_data, gpointer op_data,
CamelException *ex);
static void do_edit_messages (gpointer in_data, gpointer op_data,
CamelException *ex);
static void cleanup_edit_messages (gpointer in_data, gpointer op_data,
CamelException *ex);
static gchar *
describe_edit_messages (gpointer in_data, gboolean gerund)
{
edit_messages_input_t *input = (edit_messages_input_t *) in_data;
if (gerund)
return g_strdup_printf
(_("Opening messages from folder \"%s\""),
mail_tool_get_folder_name (input->folder));
else
return g_strdup_printf (_("Open messages from \"%s\""),
mail_tool_get_folder_name (input->folder));
}
static void
setup_edit_messages (gpointer in_data, gpointer op_data, CamelException *ex)
{
edit_messages_input_t *input = (edit_messages_input_t *) in_data;
if (!input->uids) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
/* doesn't need i18n */
"No UIDs specified to edit.");
return;
}
if (!CAMEL_IS_FOLDER (input->folder)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No folder to fetch the messages from specified.");
return;
}
camel_object_ref (CAMEL_OBJECT (input->folder));
}
static void
do_edit_messages (gpointer in_data, gpointer op_data, CamelException *ex)
{
edit_messages_input_t *input = (edit_messages_input_t *) in_data;
edit_messages_data_t *data = (edit_messages_data_t *) op_data;
int i;
data->messages = g_ptr_array_new ();
for (i = 0; i < input->uids->len; i++) {
CamelMimeMessage *message;
mail_tool_camel_lock_up ();
message = camel_folder_get_message (input->folder, input->uids->pdata[i], ex);
mail_tool_camel_lock_down ();
if (message)
g_ptr_array_add (data->messages, message);
g_free (input->uids->pdata[i]);
}
}
static void
cleanup_edit_messages (gpointer in_data, gpointer op_data,
CamelException *ex)
{
edit_messages_input_t *input = (edit_messages_input_t *) in_data;
edit_messages_data_t *data = (edit_messages_data_t *) op_data;
int i;
for (i = 0; i < data->messages->len; i++) {
GtkWidget *composer;
composer = e_msg_composer_new_with_message (data->messages->pdata[i]);
if (input->signal)
gtk_signal_connect (GTK_OBJECT (composer), "send",
input->signal, NULL);
gtk_widget_show (composer);
camel_object_unref (CAMEL_OBJECT (data->messages->pdata[i]));
}
g_ptr_array_free (input->uids, TRUE);
g_ptr_array_free (data->messages, TRUE);
camel_object_unref (CAMEL_OBJECT (input->folder));
}
static const mail_operation_spec op_edit_messages = {
describe_edit_messages,
sizeof (edit_messages_data_t),
setup_edit_messages,
do_edit_messages,
cleanup_edit_messages
};
void
mail_do_edit_messages (CamelFolder *folder, GPtrArray *uids,
GtkSignalFunc signal)
{
edit_messages_input_t *input;
input = g_new (edit_messages_input_t, 1);
input->folder = folder;
input->uids = uids;
input->signal = signal;
mail_operation_queue (&op_edit_messages, input, TRUE);
}
/* ** SETUP FOLDER ****************************************************** */
typedef struct setup_folder_input_s {
gchar *name;
CamelFolder **folder;
} setup_folder_input_t;
static gchar *describe_setup_folder (gpointer in_data, gboolean gerund);
static void setup_setup_folder (gpointer in_data, gpointer op_data,
CamelException *ex);
static void do_setup_folder (gpointer in_data, gpointer op_data,
CamelException *ex);
static void cleanup_setup_folder (gpointer in_data, gpointer op_data,
CamelException *ex);
static gchar *
describe_setup_folder (gpointer in_data, gboolean gerund)
{
setup_folder_input_t *input = (setup_folder_input_t *) in_data;
if (gerund)
return g_strdup_printf (_("Loading %s Folder"), input->name);
else
return g_strdup_printf (_("Load %s Folder"), input->name);
}
static void
setup_setup_folder (gpointer in_data, gpointer op_data, CamelException *ex)
{
}
static void
do_setup_folder (gpointer in_data, gpointer op_data, CamelException *ex)
{
setup_folder_input_t *input = (setup_folder_input_t *) in_data;
gchar *url;
url = g_strdup_printf ("mbox://%s/local/%s", evolution_dir,
input->name);
*(input->folder) = mail_tool_get_folder_from_urlname (url, "mbox",
TRUE, ex);
g_free (url);
}
static void
cleanup_setup_folder (gpointer in_data, gpointer op_data, CamelException *ex)
{
setup_folder_input_t *input = (setup_folder_input_t *) in_data;
g_free (input->name);
}
static const mail_operation_spec op_setup_folder = {
describe_setup_folder,
0,
setup_setup_folder,
do_setup_folder,
cleanup_setup_folder
};
void
mail_do_setup_folder (const char *name, CamelFolder **folder)
{
setup_folder_input_t *input;
input = g_new (setup_folder_input_t, 1);
input->name = g_strdup (name);
input->folder = folder;
mail_operation_queue (&op_setup_folder, input, TRUE);
}
/* ** VIEW MESSAGES ******************************************************* */
typedef struct view_messages_input_s {
CamelFolder *folder;
GPtrArray *uids;
FolderBrowser *fb;
} view_messages_input_t;
typedef struct view_messages_data_s {
GPtrArray *messages;
} view_messages_data_t;
static gchar *describe_view_messages (gpointer in_data, gboolean gerund);
static void setup_view_messages (gpointer in_data, gpointer op_data,
CamelException *ex);
static void do_view_messages (gpointer in_data, gpointer op_data,
CamelException *ex);
static void cleanup_view_messages (gpointer in_data, gpointer op_data,
CamelException *ex);
static gchar *
describe_view_messages (gpointer in_data, gboolean gerund)
{
view_messages_input_t *input = (view_messages_input_t *) in_data;
if (gerund)
return g_strdup_printf
(_("Viewing messages from folder \"%s\""),
mail_tool_get_folder_name (input->folder));
else
return g_strdup_printf (_("View messages from \"%s\""),
mail_tool_get_folder_name (input->folder));
}
static void
setup_view_messages (gpointer in_data, gpointer op_data, CamelException *ex)
{
view_messages_input_t *input = (view_messages_input_t *) in_data;
if (!input->uids) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
/* doesn't need i18n */
"No UIDs specified to view.");
return;
}
if (!CAMEL_IS_FOLDER (input->folder)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No folder to fetch the messages from specified.");
return;
}
if (!IS_FOLDER_BROWSER (input->fb)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"No folder browser was specified.");
return;
}
camel_object_ref (CAMEL_OBJECT (input->folder));
gtk_object_ref (GTK_OBJECT (input->fb));
}
static void
do_view_messages (gpointer in_data, gpointer op_data, CamelException *ex)
{
view_messages_input_t *input = (view_messages_input_t *) in_data;
view_messages_data_t *data = (view_messages_data_t *) op_data;
int i;
data->messages = g_ptr_array_new ();
for (i = 0; i < input->uids->len; i++) {
CamelMimeMessage *message;
mail_op_set_message (_("Retrieving message %d of %d (uid \"%s\")"),
i + 1, input->uids->len, (char *)input->uids->pdata[i]);
mail_tool_camel_lock_up ();
message = camel_folder_get_message (input->folder, input->uids->pdata[i], ex);
mail_tool_camel_lock_down ();
g_ptr_array_add (data->messages, message);
}
}
static void
cleanup_view_messages (gpointer in_data, gpointer op_data,
CamelException *ex)
{
view_messages_input_t *input = (view_messages_input_t *) in_data;
view_messages_data_t *data = (view_messages_data_t *) op_data;
int i;
for (i = 0; i < data->messages->len; i++) {
CamelMimeMessage *msg;
gchar *uid;
GtkWidget *view;
if (data->messages->pdata[i] == NULL)
continue;
msg = data->messages->pdata[i];
uid = input->uids->pdata[i];
view = mail_view_create (input->folder, uid, msg);
gtk_widget_show (view);
/*Owned by the mail_display now*/
camel_object_unref (CAMEL_OBJECT (data->messages->pdata[i]));
g_free (uid);
}
g_ptr_array_free (input->uids, TRUE);
g_ptr_array_free (data->messages, TRUE);
camel_object_unref (CAMEL_OBJECT (input->folder));
gtk_object_unref (GTK_OBJECT (input->fb));
}
static const mail_operation_spec op_view_messages = {
describe_view_messages,
sizeof (view_messages_data_t),
setup_view_messages,
do_view_messages,
cleanup_view_messages
};
void
mail_do_view_messages (CamelFolder *folder, GPtrArray *uids,
FolderBrowser *fb)
{
view_messages_input_t *input;
input = g_new (view_messages_input_t, 1);
input->folder = folder;
input->uids = uids;
input->fb = fb;
mail_operation_queue (&op_view_messages, input, TRUE);
}