From c6d3f4d7219c5175c38d29f98a65e6fa987389d3 Mon Sep 17 00:00:00 2001 From: Peter Williams Date: Thu, 10 Aug 2000 17:33:57 +0000 Subject: oops svn path=/trunk/; revision=4688 --- mail/mail-callbacks.c | 592 +++++++++++++++++++++++++++++++++++++++++++++++ mail/mail-tools.c | 620 ++++++++++++++++++++++++++++++++++++++++++++++++++ mail/mail-tools.h | 100 ++++++++ 3 files changed, 1312 insertions(+) create mode 100644 mail/mail-callbacks.c create mode 100644 mail/mail-tools.c create mode 100644 mail/mail-tools.h (limited to 'mail') diff --git a/mail/mail-callbacks.c b/mail/mail-callbacks.c new file mode 100644 index 0000000000..7ffb7dc870 --- /dev/null +++ b/mail/mail-callbacks.c @@ -0,0 +1,592 @@ +/* -*- 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 + * Peter Williams + * + * 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 +#include +#include +#include +#include +#include "mail.h" +#include "mail-config.h" +#include "mail-threads.h" +#include "mail-tools.h" +#include "mail-ops.h" +#include "mail-local.h" +#include "folder-browser.h" +#include "e-util/e-setup.h" +#include "filter/filter-editor.h" +#include "filter/filter-driver.h" +#include "widgets/e-table/e-table.h" + +/* FIXME: is there another way to do this? */ +#include "Evolution.h" +#include "evolution-storage.h" + +#include "evolution-shell-client.h" + +#ifndef HAVE_MKSTEMP +#include +#include +#endif + +struct post_send_data { + CamelFolder *folder; + gchar *uid; + guint32 flags; +}; + +static gboolean +check_configured (void) +{ + if (mail_config_is_configured ()) + return TRUE; + + mail_config_druid (); + + return mail_config_is_configured (); +} + +static void +select_first_unread (CamelFolder *folder, gpointer event_data, gpointer data) +{ + FolderBrowser *fb = FOLDER_BROWSER (data); + ETable *table = E_TABLE_SCROLLED (fb->message_list->etable)->table; + int mrow; + + mrow = e_table_view_to_model_row (table, 0); + message_list_select (fb->message_list, mrow, MESSAGE_LIST_SELECT_NEXT, + 0, CAMEL_MESSAGE_SEEN); +} + +void +fetch_mail (GtkWidget *button, gpointer user_data) +{ + MailConfigService *source; + char *url = NULL; + + if (!check_configured ()) { + GtkWidget *win = gtk_widget_get_ancestor (GTK_WIDGET (user_data), + GTK_TYPE_WINDOW); + + gnome_error_dialog_parented ("You have no mail sources " + "configured", GTK_WINDOW (win)); + return; + } + + source = mail_config_get_default_source (); + url = source->url; + + if (!url) { + GtkWidget *win = gtk_widget_get_ancestor (GTK_WIDGET (user_data), + GTK_TYPE_WINDOW); + + gnome_error_dialog_parented ("You have no mail sources " + "configured", GTK_WINDOW (win)); + return; + } + + mail_do_fetch_mail (url, source->keep_on_server, NULL, select_first_unread, user_data); +} + +static gboolean +ask_confirm_for_empty_subject (EMsgComposer *composer) +{ + GtkWidget *message_box; + int button; + + message_box = gnome_message_box_new (_("This message has no subject.\nReally send?"), + GNOME_MESSAGE_BOX_QUESTION, + GNOME_STOCK_BUTTON_YES, GNOME_STOCK_BUTTON_NO, + NULL); + + GDK_THREADS_ENTER (); + button = gnome_dialog_run_and_close (GNOME_DIALOG (message_box)); + GDK_THREADS_LEAVE (); + + if (button == 0) + return TRUE; + else + return FALSE; +} + +void +composer_send_cb (EMsgComposer *composer, gpointer data) +{ + gchar *from = NULL; + const MailConfigIdentity *id = NULL; + MailConfigService *xport = NULL; + CamelMimeMessage *message; + const char *subject; + + struct post_send_data *psd = data; + + /* Check for an identity */ + + id = mail_config_get_default_identity (); + if (!check_configured () || !id) { + GtkWidget *message; + + message = gnome_warning_dialog_parented (_("You need to configure an identity\n" + "before you can send mail."), + GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (composer), + GTK_TYPE_WINDOW))); + GDK_THREADS_ENTER (); + gnome_dialog_run_and_close (GNOME_DIALOG (message)); + GDK_THREADS_LEAVE (); + return; + } + + /* Check for a transport */ + + xport = mail_config_get_transport (); + if (!xport || !xport->url) { + GtkWidget *message; + + message = gnome_warning_dialog_parented (_("You need to configure a mail transport\n" + "before you can send mail."), + GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (composer), + GTK_TYPE_WINDOW))); + GDK_THREADS_ENTER (); + gnome_dialog_run_and_close (GNOME_DIALOG (message)); + GDK_THREADS_LEAVE (); + return; + } + + /* Generate our from address */ + + from = g_strdup (e_msg_composer_hdrs_get_from (E_MSG_COMPOSER_HDRS (composer->hdrs))); + if (!from) { + CamelInternetAddress *ciaddr; + + ciaddr = camel_internet_address_new (); + camel_internet_address_add (ciaddr, id->name, id->address); + from = camel_address_encode (CAMEL_ADDRESS (ciaddr)); + camel_object_unref (ciaddr); + } + + /* Get the message */ + + message = e_msg_composer_get_message (composer); + + /* Check for no subject */ + + subject = camel_mime_message_get_subject (message); + if (subject == NULL || subject[0] == '\0') { + if (! ask_confirm_for_empty_subject (composer)) { + camel_object_unref (CAMEL_OBJECT (message)); + return; + } + } + + if (psd) { + mail_do_send_mail (xport->url, message, from, + psd->folder, psd->uid, psd->flags, + GTK_WIDGET (composer)); + g_free (psd->uid); + } else { + mail_do_send_mail (xport->url, message, from, + NULL, NULL, 0, + GTK_WIDGET (composer)); + } +} + +static void +free_psd (GtkWidget *composer, gpointer user_data) +{ + struct post_send_data *psd = user_data; + + camel_object_unref (CAMEL_OBJECT (psd->folder)); + g_free (psd); +} + + +static GtkWidget * +create_msg_composer (const char *url) +{ + MailConfigIdentity *id; + gboolean send_html; + gchar *sig_file = NULL; + GtkWidget *composer_widget; + + id = mail_config_get_default_identity (); + send_html = mail_config_send_html (); + + if (id) + sig_file = id->sig; + + if (url != NULL) + composer_widget = e_msg_composer_new_from_url (url); + else + composer_widget = e_msg_composer_new_with_sig_file (sig_file); + + e_msg_composer_set_send_html (E_MSG_COMPOSER (composer_widget), + send_html); + + return composer_widget; +} + +void +compose_msg (GtkWidget *widget, gpointer user_data) +{ + GtkWidget *composer; + + if (!check_configured ()) + return; + + composer = create_msg_composer (NULL); + + gtk_signal_connect (GTK_OBJECT (composer), "send", + GTK_SIGNAL_FUNC (composer_send_cb), NULL); + gtk_widget_show (composer); +} + +/* Send according to a mailto (RFC 2368) URL. */ +void +send_to_url (const char *url) +{ + GtkWidget *composer; + + if (!check_configured ()) + return; + + composer = create_msg_composer (url); + + gtk_signal_connect (GTK_OBJECT (composer), "send", + GTK_SIGNAL_FUNC (composer_send_cb), NULL); + gtk_widget_show (composer); +} + +void +mail_reply (CamelFolder *folder, CamelMimeMessage *msg, const char *uid, gboolean to_all) +{ + EMsgComposer *composer; + struct post_send_data *psd; + + if (!check_configured () || !folder || + !msg || !uid) + return; + + psd = g_new (struct post_send_data, 1); + psd->folder = folder; + camel_object_ref (CAMEL_OBJECT (psd->folder)); + psd->uid = g_strdup (uid); + psd->flags = CAMEL_MESSAGE_ANSWERED; + + composer = mail_generate_reply (msg, to_all); + + gtk_signal_connect (GTK_OBJECT (composer), "send", + GTK_SIGNAL_FUNC (composer_send_cb), psd); + gtk_signal_connect (GTK_OBJECT (composer), "destroy", + GTK_SIGNAL_FUNC (free_psd), psd); + + gtk_widget_show (GTK_WIDGET (composer)); +} + +void +reply_to_sender (GtkWidget *widget, gpointer user_data) +{ + FolderBrowser *fb = FOLDER_BROWSER (user_data); + + mail_reply (fb->folder, fb->mail_display->current_message, + fb->message_list->cursor_uid, FALSE); +} + +void +reply_to_all (GtkWidget *widget, gpointer user_data) +{ + FolderBrowser *fb = FOLDER_BROWSER (user_data); + + mail_reply (fb->folder, fb->mail_display->current_message, + fb->message_list->cursor_uid, FALSE); +} + +static void +enumerate_msg (MessageList *ml, const char *uid, gpointer data) +{ + g_ptr_array_add ((GPtrArray *) data, g_strdup (uid)); +} + + +void +forward_msg (GtkWidget *widget, gpointer user_data) +{ + FolderBrowser *fb = FOLDER_BROWSER (user_data); + EMsgComposer *composer; + CamelMimeMessage *cursor_msg; + GPtrArray *uids; + + cursor_msg = fb->mail_display->current_message; + if (!check_configured () || !cursor_msg) + return; + + composer = E_MSG_COMPOSER (e_msg_composer_new ()); + + uids = g_ptr_array_new(); + message_list_foreach (fb->message_list, enumerate_msg, uids); + + gtk_signal_connect (GTK_OBJECT (composer), "send", + GTK_SIGNAL_FUNC (composer_send_cb), NULL); + + mail_do_forward_message (cursor_msg, + fb->message_list->folder, + uids, + composer); +} + +void +move_msg (GtkWidget *widget, gpointer user_data) +{ + FolderBrowser *fb = user_data; + MessageList *ml = fb->message_list; + GPtrArray *uids; + char *uri, *physical, *path; + const char *allowed_types[] = { "mail", NULL }; + extern EvolutionShellClient *global_shell_client; + static char *last = NULL; + + if (last == NULL) + last = g_strdup (""); + + evolution_shell_client_user_select_folder (global_shell_client, + _("Move message(s) to"), + last, allowed_types, &uri, &physical); + if (!uri) + return; + + path = strchr (uri, '/'); + if (path && strcmp (last, path) != 0) { + g_free (last); + last = g_strdup (path); + } + g_free (uri); + + uids = g_ptr_array_new (); + message_list_foreach (ml, enumerate_msg, uids); + mail_do_refile_messages (ml->folder, uids, physical); +} + +void +mark_all_seen (BonoboUIHandler *uih, void *user_data, const char *path) +{ + FolderBrowser *fb = FOLDER_BROWSER(user_data); + MessageList *ml = fb->message_list; + GPtrArray *uids; + + if (ml->folder == NULL) + return; + + uids = camel_folder_get_uids (ml->folder); + mail_do_flag_messages (ml->folder, uids, FALSE, + CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); +} + +void +edit_msg (GtkWidget *widget, gpointer user_data) +{ + FolderBrowser *fb = FOLDER_BROWSER (user_data); + GPtrArray *uids; + extern CamelFolder *drafts_folder; + + if (fb->folder != drafts_folder) { + GtkWidget *message; + + message = gnome_warning_dialog (_("You may only edit messages saved\n" + "in the Drafts folder.")); + GDK_THREADS_ENTER (); + gnome_dialog_run_and_close (GNOME_DIALOG (message)); + GDK_THREADS_LEAVE (); + return; + } + + uids = g_ptr_array_new(); + message_list_foreach (fb->message_list, enumerate_msg, uids); + mail_do_edit_messages (fb->folder, uids, (GtkSignalFunc) composer_send_cb); +} + +void +delete_msg (GtkWidget *button, gpointer user_data) +{ + FolderBrowser *fb = user_data; + MessageList *ml = fb->message_list; + GPtrArray *uids; + + uids = g_ptr_array_new (); + message_list_foreach (ml, enumerate_msg, uids); + mail_do_flag_messages (ml->folder, uids, TRUE, + CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_DELETED); +} + +void +expunge_folder (BonoboUIHandler *uih, void *user_data, const char *path) +{ + FolderBrowser *fb = FOLDER_BROWSER(user_data); + + e_table_model_pre_change (fb->message_list->table_model); + + if (fb->message_list->folder) + mail_do_expunge_folder (fb->message_list->folder); +} + +static void +filter_druid_clicked (GtkWidget *w, int button, FolderBrowser *fb) +{ + FilterContext *fc; + + if (button == 0) { + char *user; + + fc = gtk_object_get_data (GTK_OBJECT (w), "context"); + user = g_strdup_printf ("%s/filters.xml", evolution_dir); + rule_context_save ((RuleContext *)fc, user); + g_free (user); + } + + if (button != -1) { + gnome_dialog_close (GNOME_DIALOG (w)); + } +} + +void +filter_edit (BonoboUIHandler *uih, void *user_data, const char *path) +{ + FolderBrowser *fb = FOLDER_BROWSER (user_data); + FilterContext *fc; + char *user, *system; + GtkWidget *w; + + fc = filter_context_new(); + user = g_strdup_printf ("%s/filters.xml", evolution_dir); + system = g_strdup_printf ("%s/evolution/filtertypes.xml", EVOLUTION_DATADIR); + rule_context_load ((RuleContext *)fc, system, user); + g_free (user); + g_free (system); + + if (((RuleContext *)fc)->error) { + GtkWidget *dialog; + gchar *err; + + err = g_strdup_printf (_("Error loading filter information:\n" + "%s"), ((RuleContext *)fc)->error); + dialog = gnome_warning_dialog (err); + g_free (err); + + /* These are necessary because gtk_main, called by + * g_d_r_a_c, does a LEAVE/ENTER pair when running + * a main loop recursively. I don't know why the threads + * lock isn't being held at this point, as we're in a + * callback, but I don't ask questions. It works, and + * threads are enabled so we know that it works. + */ + GDK_THREADS_ENTER(); + gnome_dialog_run_and_close (GNOME_DIALOG (dialog)); + GDK_THREADS_LEAVE(); + return; + } + + w = filter_editor_construct (fc); + gtk_object_set_data_full (GTK_OBJECT (w), "context", fc, (GtkDestroyNotify)gtk_object_unref); + gtk_signal_connect (GTK_OBJECT (w), "clicked", filter_druid_clicked, fb); + gtk_widget_show (GTK_WIDGET (w)); +} + +void +vfolder_edit_vfolders (BonoboUIHandler *uih, void *user_data, const char *path) +{ + void vfolder_edit(void); + + vfolder_edit(); +} + +/* + *void + *providers_config (BonoboUIHandler *uih, void *user_data, const char *path) + *{ + * mail_config(); + *} + */ + +void +mail_print_msg (MailDisplay *md) +{ + GnomePrintMaster *print_master; + GnomePrintContext *print_context; + GtkWidget *preview; + + print_master = gnome_print_master_new (); + + print_context = gnome_print_master_get_context (print_master); + gtk_html_print (md->html, print_context); + + preview = GTK_WIDGET (gnome_print_master_preview_new ( + print_master, "Mail Print Preview")); + gtk_widget_show (preview); + + gtk_object_unref (GTK_OBJECT (print_master)); +} + +void +print_msg (GtkWidget *button, gpointer user_data) +{ + FolderBrowser *fb = user_data; + + mail_print_msg (fb->mail_display); +} + +void +configure_folder(BonoboUIHandler *uih, void *user_data, const char *path) +{ + FolderBrowser *fb = FOLDER_BROWSER(user_data); + + local_reconfigure_folder(fb); +} + +void +view_msg (GtkWidget *widget, gpointer user_data) +{ + FolderBrowser *fb = user_data; + GPtrArray *uids; + + if (!fb->folder) + return; + + uids = g_ptr_array_new (); + message_list_foreach (fb->message_list, enumerate_msg, uids); + mail_do_view_messages (fb->folder, uids, fb); +} + +void +view_message (BonoboUIHandler *uih, void *user_data, const char *path) +{ + view_msg (NULL, user_data); +} + +void +edit_message (BonoboUIHandler *uih, void *user_data, const char *path) +{ + edit_msg (NULL, user_data); +} + + diff --git a/mail/mail-tools.c b/mail/mail-tools.c new file mode 100644 index 0000000000..8091b55fd3 --- /dev/null +++ b/mail/mail-tools.c @@ -0,0 +1,620 @@ +/* -*- 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 + * Peter Williams + * + * 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 +#include +#include +#include "camel/camel.h" +#include "camel/providers/vee/camel-vee-folder.h" +#include "e-util/e-setup.h" +#include "mail-vfolder.h" +#include "filter/vfolder-rule.h" +#include "filter/vfolder-context.h" +#include "filter/filter-option.h" +#include "filter/filter-input.h" +#include "filter/filter-driver.h" +#include "mail.h" /*session*/ +#include "mail-tools.h" +#include "mail-local.h" + +/* **************************************** */ + +G_LOCK_DEFINE_STATIC (camel); +G_LOCK_DEFINE_STATIC (camel_locklevel); +static GPrivate *camel_locklevel = NULL; + +#define LOCK_VAL (GPOINTER_TO_INT (g_private_get (camel_locklevel))) +#define LOCK_SET(val) g_private_set (camel_locklevel, (GINT_TO_POINTER (val))) + +void mail_tool_camel_lock_up (void) +{ + G_LOCK (camel_locklevel); + + if (camel_locklevel == NULL) + camel_locklevel = g_private_new (GINT_TO_POINTER (0)); + + if (LOCK_VAL == 0) { + G_UNLOCK (camel_locklevel); + G_LOCK (camel); + G_LOCK (camel_locklevel); + } + + LOCK_SET (LOCK_VAL + 1); + + G_UNLOCK (camel_locklevel); +} + +void mail_tool_camel_lock_down (void) +{ + G_LOCK (camel_locklevel); + + if (camel_locklevel == NULL) { + g_warning ("mail_tool_camel_lock_down: lock down before a lock up?"); + camel_locklevel = g_private_new (GINT_TO_POINTER (0)); + return; + } + + LOCK_SET (LOCK_VAL - 1); + + if (LOCK_VAL == 0) + G_UNLOCK (camel); + + G_UNLOCK (camel_locklevel); +} + +/* **************************************** */ + +CamelFolder * +mail_tool_get_folder_from_urlname (const gchar *url, const gchar *name, CamelException *ex) +{ + CamelStore *store; + CamelFolder *folder; + + mail_tool_camel_lock_up(); + + store = camel_session_get_store (session, url, ex); + if (!store) { + mail_tool_camel_lock_down(); + return NULL; + } + + camel_object_ref (CAMEL_OBJECT (store)); + + camel_service_connect (CAMEL_SERVICE (store), ex); + if (camel_exception_is_set (ex)) { + camel_object_unref (CAMEL_OBJECT (store)); + mail_tool_camel_lock_down(); + return NULL; + } + + folder = camel_store_get_folder (store, name, FALSE, ex); + camel_object_unref (CAMEL_OBJECT (store)); + mail_tool_camel_lock_down(); + + return folder; +} + +gchar * +mail_tool_get_local_inbox_url (void) +{ + return g_strdup_printf ("mbox://%s/local/Inbox", evolution_dir); +} + +CamelFolder * +mail_tool_get_local_inbox (CamelException *ex) +{ + gchar *url; + CamelFolder *folder; + + url = mail_tool_get_local_inbox_url(); + folder = mail_tool_get_folder_from_urlname (url, "mbox", ex); + g_free (url); + return folder; +} + +CamelFolder * +mail_tool_get_inbox (const gchar *url, CamelException *ex) +{ + /* FIXME: should be smarter? get_default_folder, etc */ + return mail_tool_get_folder_from_urlname (url, "inbox", ex); +} + + +CamelFolder * +mail_tool_do_movemail (const gchar *source_url, CamelException *ex) +{ + gchar *dest_url; + gchar *dest_path; + const gchar *source; + CamelFolder *ret; +#ifndef MOVEMAIL_PATH + int tmpfd; +#endif + g_return_val_if_fail (strncmp (source_url, "mbox:", 5) == 0, NULL); + + /* Set up our destination. */ + + dest_url = mail_tool_get_local_inbox_url(); + dest_path = g_strdup_printf ("%s/local/Inbox/movemail", evolution_dir); + + /* Create a new movemail mailbox file of 0 size */ + +#ifndef MOVEMAIL_PATH + tmpfd = open (dest_path, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR); + + if (tmpfd == -1) { + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + "Couldn't create temporary " + "mbox `%s': %s", dest_path, g_strerror (errno)); + g_free (dest_path); + g_free (dest_url); + return NULL; + } + + close (tmpfd); +#endif + + /* Skip over "mbox:" plus host part (if any) of url. */ + + source = source_url + 5; + if (!strncmp (source, "//", 2)) + source = strchr (source + 2, '/'); + + + /* Movemail from source (source_url) to dest_path */ + + mail_tool_camel_lock_up(); + camel_movemail (source, dest_path, ex); + mail_tool_camel_lock_down(); + g_free (dest_path); + + if (camel_exception_is_set (ex)) { + g_free (dest_url); + return NULL; + } + + /* Get the CamelFolder for our dest_path. */ + + ret = mail_tool_get_folder_from_urlname (dest_url, "movemail", ex); + g_free (dest_url); + return ret; +} + +void +mail_tool_move_folder_contents (CamelFolder *source, CamelFolder *dest, gboolean use_cache, CamelException *ex) +{ + CamelUIDCache *cache; + GPtrArray *uids; + int i; + + mail_tool_camel_lock_up(); + + camel_object_ref (CAMEL_OBJECT (source)); + camel_object_ref (CAMEL_OBJECT (dest)); + + /* Get all uids of source */ + + uids = camel_folder_get_uids (source); + printf ("mail_tool_move_folder: got %d messages in source\n", uids->len); + + /* If we're using the cache, ... use it */ + + if (use_cache) { + GPtrArray *new_uids; + char *url, *p, *filename; + + url = camel_url_to_string ( + CAMEL_SERVICE (source->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) { + new_uids = camel_uid_cache_get_new_uids (cache, uids); + camel_folder_free_uids (source, uids); + uids = new_uids; + } else { + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + "Could not read UID " + "cache file \"%s\". You may " + "receive duplicate " + "messages.", filename); + } + + g_free (filename); + } else + cache = NULL; + + printf ("mail_tool_move_folder: %d of those messages are new\n", uids->len); + + /* Copy the messages */ + + for (i = 0; i < uids->len; i++) { + CamelMimeMessage *msg; + const CamelMessageInfo *info; + /* Get the message */ + + msg = camel_folder_get_message (source, uids->pdata[i], ex); + if (camel_exception_is_set (ex)) { + camel_object_unref (CAMEL_OBJECT (msg)); + goto cleanup; + } + + /* Append it to dest */ + + info = camel_folder_get_message_info (source, uids->pdata[i]); + camel_folder_append_message (dest, msg, info, ex); + if (camel_exception_is_set (ex)) { + camel_object_unref (CAMEL_OBJECT (msg)); + goto cleanup; + } + + /* (Maybe) get rid of the message */ + + camel_object_unref (CAMEL_OBJECT (msg)); + if (!use_cache) + camel_folder_delete_message (source, uids->pdata[i]); + } + + /* All done. Sync n' free. */ + + if (cache) { + 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 (source, uids); + + camel_folder_sync (source, TRUE, ex); + + cleanup: + camel_object_unref (CAMEL_OBJECT (source)); + camel_object_unref (CAMEL_OBJECT (dest)); + mail_tool_camel_lock_down(); +} + +void +mail_tool_set_uid_flags (CamelFolder *folder, const char *uid, guint32 mask, guint32 set) +{ + mail_tool_camel_lock_up(); + camel_folder_set_message_flags (folder, uid, + mask, set); + mail_tool_camel_lock_down(); +} + +gchar * +mail_tool_generate_forward_subject (CamelMimeMessage *msg) +{ + const gchar *from; + const gchar *subject; + gchar *fwd_subj; + + mail_tool_camel_lock_up(); + from = camel_mime_message_get_from (msg); + subject = camel_mime_message_get_subject (msg); + mail_tool_camel_lock_down(); + + if (from) { + if (subject && *subject) { + fwd_subj = g_strdup_printf ("[%s] %s", from, subject); + } else { + fwd_subj = g_strdup_printf ("[%s] (forwarded message)", + from); + } + } else { + if (subject && *subject) { + if (strncmp (subject, "Fwd: ", 5) == 0) + subject += 4; + fwd_subj = g_strdup_printf ("Fwd: %s", subject); + } else + fwd_subj = g_strdup ("Fwd: (no subject)"); + } + + return fwd_subj; +} + +void +mail_tool_send_via_transport (CamelTransport *transport, CamelMedium *medium, CamelException *ex) +{ + mail_tool_camel_lock_up(); + /*camel_object_ref (CAMEL_OBJECT (transport));*/ + /*camel_object_ref (CAMEL_OBJECT (medium));*/ + + camel_service_connect (CAMEL_SERVICE (transport), ex); + + if (camel_exception_is_set (ex)) + goto cleanup; + + camel_transport_send (transport, medium, ex); + + if (camel_exception_is_set (ex)) + goto cleanup; + + camel_service_disconnect (CAMEL_SERVICE (transport), ex); + + cleanup: + /*camel_object_unref (CAMEL_OBJECT (medium));*/ + /*camel_object_unref (CAMEL_OBJECT (transport));*/ + mail_tool_camel_lock_down(); +} + +CamelMimePart * +mail_tool_make_message_attachment (CamelMimeMessage *message) +{ + CamelMimePart *part; + const char *subject; + gchar *desc; + + mail_tool_camel_lock_up(); + /*camel_object_ref (CAMEL_OBJECT (message));*/ + + subject = camel_mime_message_get_subject (message); + if (subject) + desc = g_strdup_printf ("Forwarded message - %s", subject); + else + desc = g_strdup ("Forwarded message (no subjecr)"); + + part = camel_mime_part_new (); + camel_mime_part_set_disposition (part, "inline"); + camel_mime_part_set_description (part, desc); + camel_medium_set_content_object (CAMEL_MEDIUM (part), + CAMEL_DATA_WRAPPER (message)); + camel_mime_part_set_content_type (part, "message/rfc822"); + /*camel_object_unref (CAMEL_OBJECT (message));*/ + mail_tool_camel_lock_down(); + return part; +} + +CamelFolder * +mail_tool_fetch_mail_into_searchable (const char *source_url, gboolean keep_on_server, CamelException *ex) +{ + CamelFolder *search_folder = NULL; + CamelFolder *spool_folder = NULL; + + /* If using IMAP, don't do anything... */ + + if (!strncmp (source_url, "imap:", 5)) + return NULL; + + /* If fetching mail from an mbox store, safely copy it to a + * temporary store first. + */ + + if (!strncmp (source_url, "mbox:", 5)) + spool_folder = mail_tool_do_movemail (source_url, ex); + else + spool_folder = mail_tool_get_inbox (source_url, ex); + + if (camel_exception_is_set (ex)) + goto cleanup; + + /* can we perform filtering on this source? */ + + if (!(spool_folder->has_summary_capability + && spool_folder->has_search_capability)) { + + /* no :-(. Copy the messages to a local tempbox + * so that the folder browser can search it. */ + gchar *url; + + url = mail_tool_get_local_inbox_url(); + search_folder = mail_tool_get_folder_from_urlname (url, "movemail", ex); + g_free (url); + if (camel_exception_is_set (ex)) + goto cleanup; + + mail_tool_move_folder_contents (spool_folder, search_folder, keep_on_server, ex); + if (camel_exception_is_set (ex)) + goto cleanup; + + } else { + /* we can search! don't bother movemailing */ + search_folder = spool_folder; + mail_tool_camel_lock_up(); + camel_object_ref (CAMEL_OBJECT (search_folder)); + mail_tool_camel_lock_down(); + } + + cleanup: + mail_tool_camel_lock_up(); + camel_object_unref (CAMEL_OBJECT (spool_folder)); + mail_tool_camel_lock_down(); + return search_folder; +} + +static CamelFolder *get_folder_func (FilterDriver *d, const char *uri, void *data) +{ + return mail_tool_uri_to_folder_noex (uri); +} + +void +mail_tool_filter_contents_into (CamelFolder *source, CamelFolder *dest, + gpointer hook_func, gpointer hook_data, + CamelException *ex) +{ + gchar *userrules; + gchar *systemrules; + FilterContext *fc; + FilterDriver *filter; + + 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); + g_free (userrules); + g_free (systemrules); + + filter = filter_driver_new (fc, get_folder_func, 0); + + if (hook_func) + camel_object_hook_event (CAMEL_OBJECT (dest), "folder_changed", + hook_func, hook_data); + + filter_driver_run (filter, source, dest, TRUE, hook_func, hook_data); +} + +CamelFolder * +mail_tool_get_root_of_store (const char *source_uri, CamelException *ex) +{ + CamelStore *store; + CamelFolder *folder; + + mail_tool_camel_lock_up(); + + store = camel_session_get_store (session, source_uri, ex); + if (!store) { + mail_tool_camel_lock_down(); + return NULL; + } + + camel_object_ref (CAMEL_OBJECT (store)); + + camel_service_connect (CAMEL_SERVICE (store), ex); + if (camel_exception_is_set (ex)) { + camel_object_unref (CAMEL_OBJECT (store)); + mail_tool_camel_lock_down(); + return NULL; + } + + folder = camel_store_get_root_folder (store, ex); + camel_object_unref (CAMEL_OBJECT (store)); + mail_tool_camel_lock_down(); + + return folder; +} + +CamelFolder * +mail_tool_uri_to_folder (const char *uri, CamelException *ex) +{ + CamelStore *store = NULL; + CamelFolder *folder = NULL; + + if (!strncmp (uri, "vfolder:", 8)) { + folder = vfolder_uri_to_folder (uri, ex); + } else if (!strncmp (uri, "imap:", 5)) { + char *service, *ptr; + + service = g_strdup_printf ("%s/", uri); + for (ptr = service + 7; *ptr && *ptr != '/'; ptr++) {}; + ptr++; + *ptr = '\0'; + + mail_tool_camel_lock_up(); + store = camel_session_get_store (session, service, ex); + g_free (service); + if (store) { + CamelURL *url = CAMEL_SERVICE (store)->url; + char *folder_uri; + + for (ptr = (char *)(uri + 7); *ptr && *ptr != '/'; ptr++) {}; + if (*ptr == '/') { + if (url && url->path) { + ptr += strlen (url->path); + if (*ptr == '/') + ptr++; + } + + if (*ptr == '/') + ptr++; + /*for ( ; *ptr && *ptr == '/'; ptr++);*/ + + folder_uri = g_strdup (ptr); + folder = camel_store_get_folder (store, folder_uri, TRUE, ex); + g_free (folder_uri); + } + } + + mail_tool_camel_lock_down(); + + } else if (!strncmp(uri, "news:", 5)) { + mail_tool_camel_lock_up(); + store = camel_session_get_store (session, uri, ex); + if (store) { + const char *folder_path; + + folder_path = uri + 5; + folder = camel_store_get_folder (store, folder_path, FALSE, ex); + } + + mail_tool_camel_lock_down(); + + } else if (!strncmp (uri, "file:", 5)) { + folder = mail_tool_local_uri_to_folder (uri, ex); + } else { + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + "Don't know protocol to open URI `%s'", uri); + } + + if (camel_exception_is_set (ex)) { + if (folder) { + camel_object_unref (CAMEL_OBJECT (folder)); + folder = NULL; + } + } + + if (store) + camel_object_unref (CAMEL_OBJECT (store)); + + return folder; +} + +CamelFolder * +mail_tool_uri_to_folder_noex (const char *uri) +{ + CamelException ex; + CamelFolder *result; + + camel_exception_init (&ex); + result = mail_tool_uri_to_folder (uri, &ex); + + if (camel_exception_is_set (&ex)) { + gchar *msg; + GtkWidget *dialog; + + msg = g_strdup_printf ("Cannot open location `%s':\n" + "%s", + uri, + camel_exception_get_description (&ex)); + dialog = gnome_error_dialog (msg); + g_free (msg); + GDK_THREADS_ENTER (); + gnome_dialog_run_and_close (GNOME_DIALOG (dialog)); + GDK_THREADS_LEAVE (); + gtk_widget_destroy (dialog); + } + + return result; +} + diff --git a/mail/mail-tools.h b/mail/mail-tools.h new file mode 100644 index 0000000000..6d189c2ea5 --- /dev/null +++ b/mail/mail-tools.h @@ -0,0 +1,100 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * Author : + * Peter Williams + * + * 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 + */ + +#ifndef MAIL_TOOLS_H +#define MAIL_TOOLS_H + +#include + +/* A global recursive lock on Camel */ +void mail_tool_camel_lock_up (void); +void mail_tool_camel_lock_down (void); + +/* Get a CamelFolder from a root url and a foldername (uses the global session)*/ +CamelFolder * +mail_tool_get_folder_from_urlname (const gchar *url, const gchar *name, CamelException *ex); + +/* Get the url for the local inbox */ +gchar * +mail_tool_get_local_inbox_url (void); + +/* Get the CamelFolder for the local inbox */ +CamelFolder * +mail_tool_get_local_inbox (CamelException *ex); + +/* Get the "inbox" for a url (uses global session) */ +CamelFolder * +mail_tool_get_inbox (const gchar *url, CamelException *ex); + +/* Does a camel_movemail into the local movemail folder + * and returns the movemail folder that was created. */ +CamelFolder * +mail_tool_do_movemail (const gchar *source_url, CamelException *ex); + +/* Transfers all the messages from source into dest; + * source is emptied and synced. */ +void +mail_tool_move_folder_contents (CamelFolder *source, CamelFolder *dest, gboolean use_cache, CamelException *ex); + +/* Sets the flags on a message represented by a UID in a folder. */ +void +mail_tool_set_uid_flags (CamelFolder *folder, const char *uid, guint32 mask, guint32 set); + +/* Generates the subject for a message forwarding @msg */ +gchar * +mail_tool_generate_forward_subject (CamelMimeMessage *msg); + +/* Sends the medium over transport */ +void +mail_tool_send_via_transport (CamelTransport *transport, CamelMedium *medium, CamelException *ex); + +/* Make a message into an attachment */ +CamelMimePart * +mail_tool_make_message_attachment (CamelMimeMessage *message); + +/* Fetch mail from the source URL's inbox into a searchable folder. + * (not guaranteed to be local). Returns the searchable folder. */ +CamelFolder * +mail_tool_fetch_mail_into_searchable (const char *source_url, gboolean keep_on_server, CamelException *ex); + +/* Filter source into dest using the default filters. */ +void +mail_tool_filter_contents_into (CamelFolder *source, CamelFolder *dest, + gpointer hook_func, gpointer hook_data, + CamelException *ex); + +/* Get the root folder of the store specified by @source_uri */ +CamelFolder * +mail_tool_get_root_of_store (const char *source_uri, CamelException *ex); + +/* Parse the ui into a real CamelFolder any way we know how. */ +CamelFolder * +mail_tool_uri_to_folder (const char *uri, CamelException *ex); + +/* Same as above taking no exceptions, popping up a GnomeErrorDialog + * if any problems occur. */ +CamelFolder * +mail_tool_uri_to_folder_noex (const char *uri); + +#endif -- cgit