aboutsummaryrefslogtreecommitdiffstats
path: root/mail/em-composer-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'mail/em-composer-utils.c')
-rw-r--r--mail/em-composer-utils.c1887
1 files changed, 0 insertions, 1887 deletions
diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c
deleted file mode 100644
index 025b490472..0000000000
--- a/mail/em-composer-utils.c
+++ /dev/null
@@ -1,1887 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Authors: Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright 2003 Ximian, Inc. (www.ximian.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 Street #330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <gtk/gtkdialog.h>
-
-#include <gal/util/e-util.h>
-
-#include "mail-mt.h"
-#include "mail-ops.h"
-#include "mail-tools.h"
-#include "mail-config.h"
-#include "mail-session.h"
-#include "mail-send-recv.h"
-#include "mail-component.h"
-
-#include "widgets/misc/e-error.h"
-
-#include "em-utils.h"
-#include "em-composer-utils.h"
-#include "composer/e-msg-composer.h"
-#include "em-format-html.h"
-#include "em-format-quote.h"
-
-#include "e-util/e-account-list.h"
-
-#include <camel/camel-string-utils.h>
-
-static EAccount *guess_account (CamelMimeMessage *message, CamelFolder *folder);
-
-struct emcs_t {
- unsigned int ref_count;
-
- CamelFolder *drafts_folder;
- char *drafts_uid;
-
- CamelFolder *folder;
- guint32 flags, set;
- char *uid;
-};
-
-static struct emcs_t *
-emcs_new (void)
-{
- struct emcs_t *emcs;
-
- emcs = g_new (struct emcs_t, 1);
- emcs->ref_count = 1;
- emcs->drafts_folder = NULL;
- emcs->drafts_uid = NULL;
- emcs->folder = NULL;
- emcs->flags = 0;
- emcs->set = 0;
- emcs->uid = NULL;
-
- return emcs;
-}
-
-static void
-free_emcs (struct emcs_t *emcs)
-{
- if (emcs->drafts_folder)
- camel_object_unref (emcs->drafts_folder);
- g_free (emcs->drafts_uid);
-
- if (emcs->folder)
- camel_object_unref (emcs->folder);
- g_free (emcs->uid);
- g_free (emcs);
-}
-
-static void
-emcs_ref (struct emcs_t *emcs)
-{
- emcs->ref_count++;
-}
-
-static void
-emcs_unref (struct emcs_t *emcs)
-{
- emcs->ref_count--;
- if (emcs->ref_count == 0)
- free_emcs (emcs);
-}
-
-static void
-composer_destroy_cb (gpointer user_data, GObject *deadbeef)
-{
- emcs_unref (user_data);
-}
-
-static gboolean
-ask_confirm_for_unwanted_html_mail (EMsgComposer *composer, EDestination **recipients)
-{
- gboolean res;
- GString *str;
- int i;
-
- str = g_string_new("");
- for (i = 0; recipients[i] != NULL; ++i) {
- if (!e_destination_get_html_mail_pref (recipients[i])) {
- const char *name;
-
- name = e_destination_get_textrep (recipients[i], FALSE);
-
- g_string_append_printf (str, " %s\n", name);
- }
- }
-
- res = em_utils_prompt_user((GtkWindow *)composer,"/apps/evolution/mail/prompts/unwanted_html",
- "mail:ask-send-html", str->str, NULL);
- g_string_free(str, TRUE);
-
- return res;
-}
-
-static gboolean
-ask_confirm_for_empty_subject (EMsgComposer *composer)
-{
- return em_utils_prompt_user((GtkWindow *)composer, "/apps/evolution/mail/prompts/empty_subject",
- "mail:ask-send-no-subject", NULL);
-}
-
-static gboolean
-ask_confirm_for_only_bcc (EMsgComposer *composer, gboolean hidden_list_case)
-{
- /* If the user is mailing a hidden contact list, it is possible for
- them to create a message with only Bcc recipients without really
- realizing it. To try to avoid being totally confusing, I've changed
- this dialog to provide slightly different text in that case, to
- better explain what the hell is going on. */
-
- return em_utils_prompt_user((GtkWindow *)composer, "/apps/evolution/mail/prompts/only_bcc",
- hidden_list_case?"mail:ask-send-only-bcc-contact":"mail:ask-send-only-bcc", NULL);
-}
-
-struct _send_data {
- struct emcs_t *emcs;
- EMsgComposer *composer;
- gboolean send;
-};
-
-static void
-composer_send_queued_cb (CamelFolder *folder, CamelMimeMessage *msg, CamelMessageInfo *info,
- int queued, const char *appended_uid, void *data)
-{
- struct emcs_t *emcs;
- struct _send_data *send = data;
-
- emcs = send->emcs;
-
- if (queued) {
- if (emcs && emcs->drafts_folder) {
- /* delete the old draft message */
- camel_folder_set_message_flags (emcs->drafts_folder, emcs->drafts_uid,
- CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_SEEN,
- CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_SEEN);
- camel_object_unref (emcs->drafts_folder);
- emcs->drafts_folder = NULL;
- g_free (emcs->drafts_uid);
- emcs->drafts_uid = NULL;
- }
-
- if (emcs && emcs->folder) {
- /* set any replied flags etc */
- camel_folder_set_message_flags (emcs->folder, emcs->uid, emcs->flags, emcs->set);
- camel_object_unref (emcs->folder);
- emcs->folder = NULL;
- g_free (emcs->uid);
- emcs->uid = NULL;
- }
-
- gtk_widget_destroy (GTK_WIDGET (send->composer));
-
- if (send->send && camel_session_is_online (session)) {
- /* queue a message send */
- mail_send ();
- }
- } else {
- if (!emcs) {
- /* disconnect the previous signal handlers */
- g_signal_handlers_disconnect_matched (send->composer, G_SIGNAL_MATCH_FUNC, 0,
- 0, NULL, em_utils_composer_send_cb, NULL);
- g_signal_handlers_disconnect_matched (send->composer, G_SIGNAL_MATCH_FUNC, 0,
- 0, NULL, em_utils_composer_save_draft_cb, NULL);
-
- /* reconnect to the signals using a non-NULL emcs for the callback data */
- em_composer_utils_setup_default_callbacks (send->composer);
- }
-
- e_msg_composer_set_enable_autosave (send->composer, TRUE);
- gtk_widget_show (GTK_WIDGET (send->composer));
- }
-
- camel_message_info_free (info);
-
- if (send->emcs)
- emcs_unref (send->emcs);
-
- g_object_unref (send->composer);
- g_free (send);
-}
-
-static CamelMimeMessage *
-composer_get_message (EMsgComposer *composer, gboolean post, gboolean save_html_object_data, gboolean *no_recipients)
-{
- CamelMimeMessage *message = NULL;
- EDestination **recipients, **recipients_bcc;
- gboolean send_html, confirm_html;
- CamelInternetAddress *cia;
- int hidden = 0, shown = 0;
- int num = 0, num_bcc = 0;
- const char *subject;
- GConfClient *gconf;
- EAccount *account;
- int i;
-
- gconf = mail_config_get_gconf_client ();
-
- /* We should do all of the validity checks based on the composer, and not on
- the created message, as extra interaction may occur when we get the message
- (e.g. to get a passphrase to sign a message) */
-
- /* get the message recipients */
- recipients = e_msg_composer_get_recipients (composer);
-
- cia = camel_internet_address_new ();
-
- /* see which ones are visible/present, etc */
- if (recipients) {
- for (i = 0; recipients[i] != NULL; i++) {
- const char *addr = e_destination_get_address (recipients[i]);
-
- if (addr && addr[0]) {
- camel_address_decode ((CamelAddress *) cia, addr);
- if (camel_address_length ((CamelAddress *) cia) > 0) {
- camel_address_remove ((CamelAddress *) cia, -1);
- num++;
- if (e_destination_is_evolution_list (recipients[i])
- && !e_destination_list_show_addresses (recipients[i])) {
- hidden++;
- } else {
- shown++;
- }
- }
- }
- }
- }
-
- recipients_bcc = e_msg_composer_get_bcc (composer);
- if (recipients_bcc) {
- for (i = 0; recipients_bcc[i] != NULL; i++) {
- const char *addr = e_destination_get_address (recipients_bcc[i]);
-
- if (addr && addr[0]) {
- camel_address_decode ((CamelAddress *) cia, addr);
- if (camel_address_length ((CamelAddress *) cia) > 0) {
- camel_address_remove ((CamelAddress *) cia, -1);
- num_bcc++;
- }
- }
- }
-
- e_destination_freev (recipients_bcc);
- }
-
- camel_object_unref (cia);
-
- /* I'm sensing a lack of love, er, I mean recipients. */
- if (num == 0) {
- if (post) {
- if (no_recipients)
- *no_recipients = TRUE;
- } else {
- e_error_run((GtkWindow *)composer, "mail:send-no-recipients", NULL);
- goto finished;
- }
- }
-
- if (num > 0 && (num == num_bcc || shown == 0)) {
- /* this means that the only recipients are Bcc's */
- if (!ask_confirm_for_only_bcc (composer, shown == 0))
- goto finished;
- }
-
- send_html = gconf_client_get_bool (gconf, "/apps/evolution/mail/composer/send_html", NULL);
- confirm_html = gconf_client_get_bool (gconf, "/apps/evolution/mail/prompts/unwanted_html", NULL);
-
- /* Only show this warning if our default is to send html. If it isn't, we've
- manually switched into html mode in the composer and (presumably) had a good
- reason for doing this. */
- if (e_msg_composer_get_send_html (composer) && send_html && confirm_html) {
- gboolean html_problem = FALSE;
-
- if (recipients) {
- for (i = 0; recipients[i] != NULL && !html_problem; i++) {
- if (!e_destination_get_html_mail_pref (recipients[i]))
- html_problem = TRUE;
- }
- }
-
- if (html_problem) {
- html_problem = !ask_confirm_for_unwanted_html_mail (composer, recipients);
- if (html_problem)
- goto finished;
- }
- }
-
- /* Check for no subject */
- subject = e_msg_composer_get_subject (composer);
- if (subject == NULL || subject[0] == '\0') {
- if (!ask_confirm_for_empty_subject (composer))
- goto finished;
- }
-
- /* actually get the message now, this will sign/encrypt etc */
- message = e_msg_composer_get_message (composer, save_html_object_data);
- if (message == NULL)
- goto finished;
-
- /* Add info about the sending account */
- account = e_msg_composer_get_preferred_account (composer);
-
- if (account) {
- camel_medium_set_header (CAMEL_MEDIUM (message), "X-Evolution-Account", account->name);
- camel_medium_set_header (CAMEL_MEDIUM (message), "X-Evolution-Transport", account->transport->url);
- camel_medium_set_header (CAMEL_MEDIUM (message), "X-Evolution-Fcc", account->sent_folder_uri);
- if (account->id->organization && *account->id->organization) {
- char *org;
-
- org = camel_header_encode_string (account->id->organization);
- camel_medium_set_header (CAMEL_MEDIUM (message), "Organization", org);
- g_free (org);
- }
- }
-
- finished:
-
- if (recipients)
- e_destination_freev (recipients);
-
- return message;
-}
-
-static void
-got_post_folder (char *uri, CamelFolder *folder, void *data)
-{
- CamelFolder **fp = data;
-
- *fp = folder;
-
- if (folder)
- camel_object_ref (folder);
-}
-
-void
-em_utils_composer_send_cb (EMsgComposer *composer, gpointer user_data)
-{
- CamelMimeMessage *message;
- CamelMessageInfo *info;
- struct _send_data *send;
- gboolean no_recipients = FALSE;
- CamelFolder *mail_folder = NULL, *tmpfldr;
- GList *post_folders = NULL, *post_ptr;
- XEvolution *xev;
- GList *postlist;
-
- postlist = e_msg_composer_hdrs_get_post_to ((EMsgComposerHdrs *) composer->hdrs);
- while (postlist) {
- mail_msg_wait (mail_get_folder (postlist->data, 0, got_post_folder, &tmpfldr, mail_thread_new));
- if (tmpfldr)
- post_folders = g_list_append (post_folders, tmpfldr);
- postlist = g_list_next (postlist);
- }
-
- mail_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX);
- camel_object_ref (mail_folder);
-
- if (!post_folders && !mail_folder)
- return;
-
- if (!(message = composer_get_message (composer, post_folders != NULL, FALSE, &no_recipients)))
- return;
-
- if (no_recipients) {
- /* we're doing a post with no recipients */
- camel_object_unref (mail_folder);
- mail_folder = NULL;
- }
-
- if (mail_folder) {
- /* mail the message */
- info = camel_message_info_new ();
- info->flags = CAMEL_MESSAGE_SEEN;
-
- send = g_malloc (sizeof (*send));
- send->emcs = user_data;
- if (send->emcs)
- emcs_ref (send->emcs);
- send->send = TRUE;
- send->composer = composer;
- g_object_ref (composer);
- gtk_widget_hide (GTK_WIDGET (composer));
-
- e_msg_composer_set_enable_autosave (composer, FALSE);
-
- mail_append_mail (mail_folder, message, info, composer_send_queued_cb, send);
- camel_object_unref (mail_folder);
- }
-
- if (post_folders) {
- /* Remove the X-Evolution* headers if we are in Post-To mode */
- xev = mail_tool_remove_xevolution_headers (message);
- mail_tool_destroy_xevolution (xev);
-
- /* mail the message */
- info = camel_message_info_new ();
- info->flags = CAMEL_MESSAGE_SEEN;
-
- post_ptr = post_folders;
- while (post_ptr) {
- send = g_malloc (sizeof (*send));
- send->emcs = user_data;
- if (send->emcs)
- emcs_ref (send->emcs);
- send->send = FALSE;
- send->composer = composer;
- g_object_ref (composer);
- gtk_widget_hide (GTK_WIDGET (composer));
-
- e_msg_composer_set_enable_autosave (composer, FALSE);
-
- mail_append_mail ((CamelFolder *) post_ptr->data, message, info, composer_send_queued_cb, send);
- camel_object_unref ((CamelFolder *) post_ptr->data);
-
- post_ptr = g_list_next (post_ptr);
- }
- }
-
- camel_object_unref (message);
-}
-
-struct _save_draft_info {
- struct emcs_t *emcs;
- EMsgComposer *composer;
- int quit;
-};
-
-static void
-save_draft_done (CamelFolder *folder, CamelMimeMessage *msg, CamelMessageInfo *info, int ok,
- const char *appended_uid, void *user_data)
-{
- struct _save_draft_info *sdi = user_data;
- struct emcs_t *emcs;
- CORBA_Environment ev;
-
- if (!ok)
- goto done;
-
- CORBA_exception_init (&ev);
- GNOME_GtkHTML_Editor_Engine_runCommand (sdi->composer->editor_engine, "saved", &ev);
- CORBA_exception_free (&ev);
-
- if ((emcs = sdi->emcs) == NULL) {
- emcs = emcs_new ();
-
- /* disconnect the previous signal handlers */
- g_signal_handlers_disconnect_by_func (sdi->composer, G_CALLBACK (em_utils_composer_send_cb), NULL);
- g_signal_handlers_disconnect_by_func (sdi->composer, G_CALLBACK (em_utils_composer_save_draft_cb), NULL);
-
- /* reconnect to the signals using a non-NULL emcs for the callback data */
- em_composer_utils_setup_default_callbacks (sdi->composer);
- }
-
- if (emcs->drafts_folder) {
- /* delete the original draft message */
- camel_folder_set_message_flags (emcs->drafts_folder, emcs->drafts_uid,
- CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_SEEN,
- CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_SEEN);
- camel_object_unref (emcs->drafts_folder);
- emcs->drafts_folder = NULL;
- g_free (emcs->drafts_uid);
- emcs->drafts_uid = NULL;
- }
-
- if (emcs->folder) {
- /* set the replied flags etc */
- camel_folder_set_message_flags (emcs->folder, emcs->uid, emcs->flags, emcs->set);
- camel_object_unref (emcs->folder);
- emcs->folder = NULL;
- g_free (emcs->uid);
- emcs->uid = NULL;
- }
-
- if (appended_uid) {
- camel_object_ref (folder);
- emcs->drafts_folder = folder;
- emcs->drafts_uid = g_strdup (appended_uid);
- }
-
- if (sdi->quit)
- gtk_widget_destroy (GTK_WIDGET (sdi->composer));
-
- done:
- g_object_unref (sdi->composer);
- if (sdi->emcs)
- emcs_unref (sdi->emcs);
- g_free (info);
- g_free (sdi);
-}
-
-static void
-save_draft_folder (char *uri, CamelFolder *folder, gpointer data)
-{
- CamelFolder **save = data;
-
- if (folder) {
- *save = folder;
- camel_object_ref (folder);
- }
-}
-
-void
-em_utils_composer_save_draft_cb (EMsgComposer *composer, int quit, gpointer user_data)
-{
- const char *default_drafts_folder_uri = mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_DRAFTS);
- CamelFolder *drafts_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_DRAFTS);
- struct _save_draft_info *sdi;
- CamelFolder *folder = NULL;
- CamelMimeMessage *msg;
- CamelMessageInfo *info;
- EAccount *account;
-
- account = e_msg_composer_get_preferred_account (composer);
- if (account && account->drafts_folder_uri &&
- strcmp (account->drafts_folder_uri, default_drafts_folder_uri) != 0) {
- int id;
-
- id = mail_get_folder (account->drafts_folder_uri, 0, save_draft_folder, &folder, mail_thread_new);
- mail_msg_wait (id);
-
- if (!folder) {
- if (e_error_run((GtkWindow *)composer, "mail:ask-default-drafts", NULL) != GTK_RESPONSE_YES)
- return;
-
- folder = drafts_folder;
- camel_object_ref (drafts_folder);
- }
- } else {
- folder = drafts_folder;
- camel_object_ref (folder);
- }
-
- msg = e_msg_composer_get_message_draft (composer);
-
- info = g_new0 (CamelMessageInfo, 1);
- info->flags = CAMEL_MESSAGE_DRAFT | CAMEL_MESSAGE_SEEN;
-
- sdi = g_malloc (sizeof (struct _save_draft_info));
- sdi->composer = composer;
- g_object_ref (composer);
- sdi->emcs = user_data;
- if (sdi->emcs)
- emcs_ref (sdi->emcs);
- sdi->quit = quit;
-
- mail_append_mail (folder, msg, info, save_draft_done, sdi);
- camel_object_unref (folder);
- camel_object_unref (msg);
-}
-
-void
-em_composer_utils_setup_callbacks (EMsgComposer *composer, CamelFolder *folder, const char *uid,
- guint32 flags, guint32 set, CamelFolder *drafts, const char *drafts_uid)
-{
- struct emcs_t *emcs;
-
- emcs = emcs_new ();
-
- if (folder && uid) {
- camel_object_ref (folder);
- emcs->folder = folder;
- emcs->uid = g_strdup (uid);
- emcs->flags = flags;
- emcs->set = set;
- }
-
- if (drafts && drafts_uid) {
- camel_object_ref (drafts);
- emcs->drafts_folder = drafts;
- emcs->drafts_uid = g_strdup (drafts_uid);
- }
-
- g_signal_connect (composer, "send", G_CALLBACK (em_utils_composer_send_cb), emcs);
- g_signal_connect (composer, "save-draft", G_CALLBACK (em_utils_composer_save_draft_cb), emcs);
-
- g_object_weak_ref ((GObject *) composer, (GWeakNotify) composer_destroy_cb, emcs);
-}
-
-/* Composing messages... */
-
-static EMsgComposer *
-create_new_composer (const char *subject, const char *fromuri)
-{
- EMsgComposer *composer;
- EAccount *account = NULL;
-
- composer = e_msg_composer_new ();
-
- if (fromuri)
- account = mail_config_get_account_by_source_url(fromuri);
-
- e_msg_composer_set_headers (composer, account?account->name:NULL, NULL, NULL, NULL, subject);
-
- em_composer_utils_setup_default_callbacks (composer);
-
- return composer;
-}
-
-/**
- * em_utils_compose_new_message:
- *
- * Opens a new composer window as a child window of @parent's toplevel
- * window.
- **/
-void
-em_utils_compose_new_message (const char *fromuri)
-{
- GtkWidget *composer;
-
- composer = (GtkWidget *) create_new_composer ("", fromuri);
-
- e_msg_composer_unset_changed ((EMsgComposer *)composer);
- e_msg_composer_drop_editor_undo ((EMsgComposer *)composer);
-
- gtk_widget_show (composer);
-}
-
-/**
- * em_utils_compose_new_message_with_mailto:
- * @url: mailto url
- *
- * Opens a new composer window as a child window of @parent's toplevel
- * window. If @url is non-NULL, the composer fields will be filled in
- * according to the values in the mailto url.
- **/
-void
-em_utils_compose_new_message_with_mailto (const char *url, const char *fromuri)
-{
- EMsgComposer *composer;
- EAccount *account = NULL;
-
- if (url != NULL)
- composer = e_msg_composer_new_from_url (url);
- else
- composer = e_msg_composer_new ();
-
- em_composer_utils_setup_default_callbacks (composer);
-
- if (fromuri
- && (account = mail_config_get_account_by_source_url(fromuri)))
- e_msg_composer_hdrs_set_from_account((EMsgComposerHdrs *)composer->hdrs, account->name);
-
- e_msg_composer_unset_changed (composer);
- e_msg_composer_drop_editor_undo (composer);
-
- gtk_widget_show ((GtkWidget *) composer);
-}
-
-/**
- * em_utils_post_to_folder:
- * @folder: folder
- *
- * Opens a new composer window as a child window of @parent's toplevel
- * window. If @folder is non-NULL, the composer will default to posting
- * mail to the folder specified by @folder.
- **/
-void
-em_utils_post_to_folder (CamelFolder *folder)
-{
- EMsgComposer *composer;
- EAccount *account;
-
- composer = e_msg_composer_new_with_type (E_MSG_COMPOSER_POST);
-
- if (folder != NULL) {
- char *url = mail_tools_folder_to_url (folder);
-
- e_msg_composer_hdrs_set_post_to ((EMsgComposerHdrs *) ((EMsgComposer *) composer)->hdrs, url);
- g_free (url);
-
- url = camel_url_to_string (CAMEL_SERVICE (folder->parent_store)->url, CAMEL_URL_HIDE_ALL);
- account = mail_config_get_account_by_source_url (url);
- g_free (url);
-
- if (account)
- e_msg_composer_hdrs_set_from_account ((EMsgComposerHdrs *) ((EMsgComposer *) composer)->hdrs, account->name);
- }
-
- em_composer_utils_setup_default_callbacks (composer);
-
- e_msg_composer_unset_changed (composer);
- e_msg_composer_drop_editor_undo (composer);
-
- gtk_widget_show ((GtkWidget *) composer);
-}
-
-/**
- * em_utils_post_to_url:
- * @url: mailto url
- *
- * Opens a new composer window as a child window of @parent's toplevel
- * window. If @url is non-NULL, the composer will default to posting
- * mail to the folder specified by @url.
- **/
-void
-em_utils_post_to_url (const char *url)
-{
- EMsgComposer *composer;
-
- composer = e_msg_composer_new_with_type (E_MSG_COMPOSER_POST);
-
- if (url != NULL)
- e_msg_composer_hdrs_set_post_to ((EMsgComposerHdrs *) ((EMsgComposer *) composer)->hdrs, url);
-
- em_composer_utils_setup_default_callbacks (composer);
-
- e_msg_composer_unset_changed (composer);
- e_msg_composer_drop_editor_undo (composer);
-
- gtk_widget_show ((GtkWidget *) composer);
-}
-
-/* Editing messages... */
-
-static void
-edit_message (CamelMimeMessage *message, CamelFolder *drafts, const char *uid)
-{
- EMsgComposer *composer;
-
- composer = e_msg_composer_new_with_message (message);
- em_composer_utils_setup_callbacks (composer, NULL, NULL, 0, 0, drafts, uid);
- e_msg_composer_unset_changed (composer);
- e_msg_composer_drop_editor_undo (composer);
-
- gtk_widget_show (GTK_WIDGET (composer));
-}
-
-/**
- * em_utils_edit_message:
- * @message: message to edit
- *
- * Opens a composer filled in with the headers/mime-parts/etc of
- * @message.
- **/
-void
-em_utils_edit_message (CamelMimeMessage *message)
-{
- g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
-
- edit_message (message, NULL, NULL);
-}
-
-static void
-edit_messages (CamelFolder *folder, GPtrArray *uids, GPtrArray *msgs, void *user_data)
-{
- gboolean replace = GPOINTER_TO_INT (user_data);
- int i;
-
- if (msgs == NULL)
- return;
-
- for (i = 0; i < msgs->len; i++) {
- camel_medium_remove_header (CAMEL_MEDIUM (msgs->pdata[i]), "X-Mailer");
-
- if (replace)
- edit_message (msgs->pdata[i], folder, uids->pdata[i]);
- else
- edit_message (msgs->pdata[i], NULL, NULL);
- }
-}
-
-/**
- * em_utils_edit_messages:
- * @folder: folder containing messages to edit
- * @uids: uids of messages to edit
- * @replace: replace the existing message(s) when sent or saved.
- *
- * Opens a composer for each message to be edited.
- **/
-void
-em_utils_edit_messages (CamelFolder *folder, GPtrArray *uids, gboolean replace)
-{
- g_return_if_fail (CAMEL_IS_FOLDER (folder));
- g_return_if_fail (uids != NULL);
-
- mail_get_messages (folder, uids, edit_messages, GINT_TO_POINTER (replace));
-}
-
-/* Forwarding messages... */
-static void
-forward_attached (CamelFolder *folder, GPtrArray *messages, CamelMimePart *part, char *subject, const char *fromuri)
-{
- EMsgComposer *composer;
-
- composer = create_new_composer (subject, fromuri);
- e_msg_composer_attach (composer, part);
-
- e_msg_composer_unset_changed (composer);
- e_msg_composer_drop_editor_undo (composer);
-
- gtk_widget_show (GTK_WIDGET (composer));
-}
-
-static void
-forward_attached_cb (CamelFolder *folder, GPtrArray *messages, CamelMimePart *part, char *subject, void *user_data)
-{
- if (part)
- forward_attached(folder, messages, part, subject, (char *)user_data);
- g_free(user_data);
-}
-
-/**
- * em_utils_forward_attached:
- * @folder: folder containing messages to forward
- * @uids: uids of messages to forward
- * @fromuri: from folder uri
- *
- * If there is more than a single message in @uids, a multipart/digest
- * will be constructed and attached to a new composer window preset
- * with the appropriate header defaults for forwarding the first
- * message in the list. If only one message is to be forwarded, it is
- * forwarded as a simple message/rfc822 attachment.
- **/
-void
-em_utils_forward_attached (CamelFolder *folder, GPtrArray *uids, const char *fromuri)
-{
- g_return_if_fail (CAMEL_IS_FOLDER (folder));
- g_return_if_fail (uids != NULL);
-
- mail_build_attachment (folder, uids, forward_attached_cb, g_strdup(fromuri));
-}
-
-static void
-forward_non_attached (GPtrArray *messages, int style, const char *fromuri)
-{
- CamelMimeMessage *message;
- EMsgComposer *composer;
- char *subject, *text;
- int i;
- guint32 flags;
-
- if (messages->len == 0)
- return;
-
- flags = EM_FORMAT_QUOTE_HEADERS;
- if (style == MAIL_CONFIG_FORWARD_QUOTED)
- flags |= EM_FORMAT_QUOTE_CITE;
-
- for (i = 0; i < messages->len; i++) {
- ssize_t len;
-
- message = messages->pdata[i];
- subject = mail_tool_generate_forward_subject (message);
-
- text = em_utils_message_to_html (message, _("-------- Forwarded Message --------"), flags, &len, NULL);
-
- if (text) {
- composer = create_new_composer (subject, fromuri);
-
- e_msg_composer_set_body_text (composer, text, len);
-
- e_msg_composer_unset_changed (composer);
- e_msg_composer_drop_editor_undo (composer);
-
- gtk_widget_show (GTK_WIDGET (composer));
-
- g_free (text);
- }
-
- g_free (subject);
- }
-}
-
-static void
-forward_inline (CamelFolder *folder, GPtrArray *uids, GPtrArray *messages, void *user_data)
-{
- forward_non_attached (messages, MAIL_CONFIG_FORWARD_INLINE, (char *)user_data);
- g_free(user_data);
-}
-
-/**
- * em_utils_forward_inline:
- * @folder: folder containing messages to forward
- * @uids: uids of messages to forward
- * @fromuri: from folder/account uri
- *
- * Forwards each message in the 'inline' form, each in its own composer window.
- **/
-void
-em_utils_forward_inline (CamelFolder *folder, GPtrArray *uids, const char *fromuri)
-{
- g_return_if_fail (CAMEL_IS_FOLDER (folder));
- g_return_if_fail (uids != NULL);
-
- mail_get_messages (folder, uids, forward_inline, g_strdup(fromuri));
-}
-
-static void
-forward_quoted (CamelFolder *folder, GPtrArray *uids, GPtrArray *messages, void *user_data)
-{
- forward_non_attached (messages, MAIL_CONFIG_FORWARD_QUOTED, (char *)user_data);
- g_free(user_data);
-}
-
-/**
- * em_utils_forward_quoted:
- * @folder: folder containing messages to forward
- * @uids: uids of messages to forward
- * @fromuri: from folder uri
- *
- * Forwards each message in the 'quoted' form (each line starting with
- * a "> "), each in its own composer window.
- **/
-void
-em_utils_forward_quoted (CamelFolder *folder, GPtrArray *uids, const char *fromuri)
-{
- g_return_if_fail (CAMEL_IS_FOLDER (folder));
- g_return_if_fail (uids != NULL);
-
- mail_get_messages (folder, uids, forward_quoted, g_strdup(fromuri));
-}
-
-/**
- * em_utils_forward_message:
- * @parent: parent window
- * @message: message to be forwarded
- * @fromuri: from folder uri
- *
- * Forwards a message in the user's configured default style.
- **/
-void
-em_utils_forward_message (CamelMimeMessage *message, const char *fromuri)
-{
- GPtrArray *messages;
- CamelMimePart *part;
- GConfClient *gconf;
- char *subject;
- int mode;
-
- messages = g_ptr_array_new ();
- g_ptr_array_add (messages, message);
-
- gconf = mail_config_get_gconf_client ();
- mode = gconf_client_get_int (gconf, "/apps/evolution/mail/format/forward_style", NULL);
-
- switch (mode) {
- case MAIL_CONFIG_FORWARD_ATTACHED:
- default:
- part = mail_tool_make_message_attachment (message);
-
- subject = mail_tool_generate_forward_subject (message);
-
- forward_attached (NULL, messages, part, subject, fromuri);
- camel_object_unref (part);
- g_free (subject);
- break;
- case MAIL_CONFIG_FORWARD_INLINE:
- forward_non_attached (messages, MAIL_CONFIG_FORWARD_INLINE, fromuri);
- break;
- case MAIL_CONFIG_FORWARD_QUOTED:
- forward_non_attached (messages, MAIL_CONFIG_FORWARD_QUOTED, fromuri);
- break;
- }
-
- g_ptr_array_free (messages, TRUE);
-}
-
-/**
- * em_utils_forward_messages:
- * @folder: folder containing messages to forward
- * @uids: uids of messages to forward
- *
- * Forwards a group of messages in the user's configured default
- * style.
- **/
-void
-em_utils_forward_messages (CamelFolder *folder, GPtrArray *uids, const char *fromuri)
-{
- GConfClient *gconf;
- int mode;
-
- gconf = mail_config_get_gconf_client ();
- mode = gconf_client_get_int (gconf, "/apps/evolution/mail/format/forward_style", NULL);
-
- switch (mode) {
- case MAIL_CONFIG_FORWARD_ATTACHED:
- default:
- em_utils_forward_attached (folder, uids, fromuri);
- break;
- case MAIL_CONFIG_FORWARD_INLINE:
- em_utils_forward_inline (folder, uids, fromuri);
- break;
- case MAIL_CONFIG_FORWARD_QUOTED:
- em_utils_forward_quoted (folder, uids, fromuri);
- break;
- }
-}
-
-/* Redirecting messages... */
-
-static EMsgComposer *
-redirect_get_composer (CamelMimeMessage *message)
-{
- EMsgComposer *composer;
- EAccount *account;
-
- /* QMail will refuse to send a message if it finds one of
- it's Delivered-To headers in the message, so remove all
- Delivered-To headers. Fixes bug #23635. */
- while (camel_medium_get_header (CAMEL_MEDIUM (message), "Delivered-To"))
- camel_medium_remove_header (CAMEL_MEDIUM (message), "Delivered-To");
-
- account = guess_account (message, NULL);
-
- composer = e_msg_composer_new_redirect (message, account ? account->name : NULL);
-
- em_composer_utils_setup_default_callbacks (composer);
-
- return composer;
-}
-
-/**
- * em_utils_redirect_message:
- * @message: message to redirect
- *
- * Opens a composer to redirect @message (Note: only headers will be
- * editable). Adds Resent-From/Resent-To/etc headers.
- **/
-void
-em_utils_redirect_message (CamelMimeMessage *message)
-{
- EMsgComposer *composer;
- CamelDataWrapper *wrapper;
-
- g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
-
- composer = redirect_get_composer (message);
-
- wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (message));
-
- gtk_widget_show (GTK_WIDGET (composer));
- e_msg_composer_unset_changed (composer);
- e_msg_composer_drop_editor_undo (composer);
-}
-
-static void
-redirect_msg (CamelFolder *folder, const char *uid, CamelMimeMessage *message, void *user_data)
-{
- if (message == NULL)
- return;
-
- em_utils_redirect_message (message);
-}
-
-/**
- * em_utils_redirect_message_by_uid:
- * @folder: folder containing message to be redirected
- * @uid: uid of message to be redirected
- *
- * Opens a composer to redirect the message (Note: only headers will
- * be editable). Adds Resent-From/Resent-To/etc headers.
- **/
-void
-em_utils_redirect_message_by_uid (CamelFolder *folder, const char *uid)
-{
- g_return_if_fail (CAMEL_IS_FOLDER (folder));
- g_return_if_fail (uid != NULL);
-
- mail_get_message (folder, uid, redirect_msg, NULL, mail_thread_new);
-}
-
-/* Replying to messages... */
-
-static GHashTable *
-generate_account_hash (void)
-{
- GHashTable *account_hash;
- EAccount *account, *def;
- EAccountList *accounts;
- EIterator *iter;
-
- accounts = mail_config_get_accounts ();
- account_hash = g_hash_table_new (camel_strcase_hash, camel_strcase_equal);
-
- /* add the default account to the hash first */
- if ((def = mail_config_get_default_account ())) {
- if (def->id->address)
- g_hash_table_insert (account_hash, (char *) def->id->address, (void *) def);
- }
-
- iter = e_list_get_iterator ((EList *) accounts);
- while (e_iterator_is_valid (iter)) {
- account = (EAccount *) e_iterator_get (iter);
-
- if (account->id->address) {
- EAccount *acnt;
-
- /* Accounts with identical email addresses that are enabled
- * take precedence over the accounts that aren't. If all
- * accounts with matching email addresses are disabled, then
- * the first one in the list takes precedence. The default
- * account always takes precedence no matter what.
- */
- acnt = g_hash_table_lookup (account_hash, account->id->address);
- if (acnt && acnt != def && !acnt->enabled && account->enabled) {
- g_hash_table_remove (account_hash, acnt->id->address);
- acnt = NULL;
- }
-
- if (!acnt)
- g_hash_table_insert (account_hash, (char *) account->id->address, (void *) account);
- }
-
- e_iterator_next (iter);
- }
-
- g_object_unref (iter);
-
- return account_hash;
-}
-
-static EDestination **
-em_utils_camel_address_to_destination (CamelInternetAddress *iaddr)
-{
- EDestination *dest, **destv;
- int n, i, j;
-
- if (iaddr == NULL)
- return NULL;
-
- if ((n = camel_address_length ((CamelAddress *) iaddr)) == 0)
- return NULL;
-
- destv = g_malloc (sizeof (EDestination *) * (n + 1));
- for (i = 0, j = 0; i < n; i++) {
- const char *name, *addr;
-
- if (camel_internet_address_get (iaddr, i, &name, &addr)) {
- dest = e_destination_new ();
- e_destination_set_name (dest, name);
- e_destination_set_email (dest, addr);
-
- destv[j++] = dest;
- }
- }
-
- if (j == 0) {
- g_free (destv);
- return NULL;
- }
-
- destv[j] = NULL;
-
- return destv;
-}
-
-static EMsgComposer *
-reply_get_composer (CamelMimeMessage *message, EAccount *account,
- CamelInternetAddress *to, CamelInternetAddress *cc,
- CamelFolder *folder, const char *postto)
-{
- const char *message_id, *references;
- EDestination **tov, **ccv;
- EMsgComposer *composer;
- char *subject;
-
- g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
- g_return_val_if_fail (to == NULL || CAMEL_IS_INTERNET_ADDRESS (to), NULL);
- g_return_val_if_fail (cc == NULL || CAMEL_IS_INTERNET_ADDRESS (cc), NULL);
-
- /* construct the tov/ccv */
- tov = em_utils_camel_address_to_destination (to);
- ccv = em_utils_camel_address_to_destination (cc);
-
- if (tov || ccv) {
- if (postto)
- composer = e_msg_composer_new_with_type (E_MSG_COMPOSER_MAIL_POST);
- else
- composer = e_msg_composer_new_with_type (E_MSG_COMPOSER_MAIL);
- } else
- composer = e_msg_composer_new_with_type (E_MSG_COMPOSER_POST);
-
- /* Set the subject of the new message. */
- if ((subject = (char *) camel_mime_message_get_subject (message))) {
- if (strncasecmp (subject, "Re: ", 4) != 0)
- subject = g_strdup_printf ("Re: %s", subject);
- else
- subject = g_strdup (subject);
- } else {
- subject = g_strdup ("");
- }
-
- e_msg_composer_set_headers (composer, account ? account->name : NULL, tov, ccv, NULL, subject);
-
- g_free (subject);
-
- /* add post-to, if nessecary */
- if (postto) {
- char *store_url = NULL;
-
- if (folder) {
- store_url = camel_url_to_string (CAMEL_SERVICE (folder->parent_store)->url, CAMEL_URL_HIDE_ALL);
- if (store_url[strlen (store_url) - 1] == '/')
- store_url[strlen (store_url)-1] = '\0';
- }
-
- e_msg_composer_hdrs_set_post_to_base (E_MSG_COMPOSER_HDRS (composer->hdrs), store_url ? store_url : "", postto);
- g_free (store_url);
- }
-
- /* Add In-Reply-To and References. */
- message_id = camel_medium_get_header (CAMEL_MEDIUM (message), "Message-Id");
- references = camel_medium_get_header (CAMEL_MEDIUM (message), "References");
- if (message_id) {
- char *reply_refs;
-
- e_msg_composer_add_header (composer, "In-Reply-To", message_id);
-
- if (references)
- reply_refs = g_strdup_printf ("%s %s", references, message_id);
- else
- reply_refs = g_strdup (message_id);
-
- e_msg_composer_add_header (composer, "References", reply_refs);
- g_free (reply_refs);
- } else if (references) {
- e_msg_composer_add_header (composer, "References", references);
- }
-
- e_msg_composer_drop_editor_undo (composer);
-
- return composer;
-}
-
-static EAccount *
-guess_account_folder(CamelFolder *folder)
-{
- EAccount *account;
- char *tmp;
-
- tmp = camel_url_to_string(CAMEL_SERVICE(folder->parent_store)->url, CAMEL_URL_HIDE_ALL);
- account = mail_config_get_account_by_source_url(tmp);
- g_free(tmp);
-
- return account;
-}
-
-static EAccount *
-guess_account (CamelMimeMessage *message, CamelFolder *folder)
-{
- GHashTable *account_hash = NULL;
- EAccount *account = NULL;
- const char *tmp;
- int i, j;
- char *types[2] = { CAMEL_RECIPIENT_TYPE_TO, CAMEL_RECIPIENT_TYPE_CC };
-
- /* check for newsgroup header */
- if (folder
- && camel_medium_get_header((CamelMedium *)message, "Newsgroups")
- && (account = guess_account_folder(folder)))
- return account;
-
- /* then recipient (to/cc) in account table */
- account_hash = generate_account_hash ();
- for (j=0;account == NULL && j<2;j++) {
- const CamelInternetAddress *to;
-
- to = camel_mime_message_get_recipients(message, types[j]);
- if (to) {
- for (i = 0; camel_internet_address_get(to, i, NULL, &tmp); i++) {
- account = g_hash_table_lookup(account_hash, tmp);
- if (account)
- break;
- }
- }
- }
- g_hash_table_destroy(account_hash);
-
- /* then message source */
- if (account == NULL
- && (tmp = camel_mime_message_get_source(message)))
- account = mail_config_get_account_by_source_url(tmp);
-
- /* and finally, source folder */
- if (account == NULL
- && folder)
- account = guess_account_folder(folder);
-
- return account;
-}
-
-static void
-get_reply_sender (CamelMimeMessage *message, CamelInternetAddress **to, const char **postto)
-{
- const CamelInternetAddress *reply_to;
- const char *name, *addr, *posthdr;
- int i;
-
- /* check whether there is a 'Newsgroups: ' header in there */
- posthdr = camel_medium_get_header (CAMEL_MEDIUM (message), "Newsgroups");
- if (posthdr && postto) {
- *postto = posthdr;
- while (**postto == ' ')
- (*postto)++;
- return;
- }
-
- reply_to = camel_mime_message_get_reply_to (message);
- if (!reply_to)
- reply_to = camel_mime_message_get_from (message);
-
- if (reply_to) {
- *to = camel_internet_address_new ();
-
- for (i = 0; camel_internet_address_get (reply_to, i, &name, &addr); i++)
- camel_internet_address_add (*to, name, addr);
- }
-}
-
-static gboolean
-get_reply_list (CamelMimeMessage *message, CamelInternetAddress **to)
-{
- const char *header, *p;
- char *addr;
-
- /* Examples:
- *
- * List-Post: <mailto:list@host.com>
- * List-Post: <mailto:moderator@host.com?subject=list%20posting>
- * List-Post: NO (posting not allowed on this list)
- */
- if (!(header = camel_medium_get_header ((CamelMedium *) message, "List-Post")))
- return FALSE;
-
- while (*header == ' ' || *header == '\t')
- header++;
-
- /* check for NO */
- if (!strncasecmp (header, "NO", 2))
- return FALSE;
-
- /* Search for the first mailto angle-bracket enclosed URL.
- * (See rfc2369, Section 2, paragraph 3 for details) */
- if (!(header = camel_strstrcase (header, "<mailto:")))
- return FALSE;
-
- header += 8;
-
- p = header;
- while (*p && !strchr ("?>", *p))
- p++;
-
- addr = g_strndup (header, p - header);
-
- *to = camel_internet_address_new ();
- camel_internet_address_add (*to, NULL, addr);
-
- g_free (addr);
-
- return TRUE;
-}
-
-static void
-concat_unique_addrs (CamelInternetAddress *dest, const CamelInternetAddress *src, GHashTable *rcpt_hash)
-{
- const char *name, *addr;
- int i;
-
- for (i = 0; camel_internet_address_get (src, i, &name, &addr); i++) {
- if (!g_hash_table_lookup (rcpt_hash, addr)) {
- camel_internet_address_add (dest, name, addr);
- g_hash_table_insert (rcpt_hash, (char *) addr, GINT_TO_POINTER (1));
- }
- }
-}
-
-static void
-get_reply_all (CamelMimeMessage *message, CamelInternetAddress **to, CamelInternetAddress **cc, const char **postto)
-{
- const CamelInternetAddress *reply_to, *to_addrs, *cc_addrs;
- const char *name, *addr, *posthdr;
- GHashTable *rcpt_hash;
- int i;
-
- /* check whether there is a 'Newsgroups: ' header in there */
- posthdr = camel_medium_get_header (CAMEL_MEDIUM(message), "Newsgroups");
- if (posthdr && postto) {
- *postto = posthdr;
- while (**postto == ' ')
- (*postto)++;
- }
-
- rcpt_hash = generate_account_hash ();
-
- reply_to = camel_mime_message_get_reply_to (message);
- if (!reply_to)
- reply_to = camel_mime_message_get_from (message);
-
- to_addrs = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_TO);
- cc_addrs = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_CC);
-
- *to = camel_internet_address_new ();
- *cc = camel_internet_address_new ();
-
- if (reply_to) {
- for (i = 0; camel_internet_address_get (reply_to, i, &name, &addr); i++) {
- /* ignore references to the Reply-To address in the To and Cc lists */
- if (addr && !g_hash_table_lookup (rcpt_hash, addr)) {
- /* In the case that we are doing a Reply-To-All, we do not want
- to include the user's email address because replying to oneself
- is kinda silly. */
-
- camel_internet_address_add (*to, name, addr);
- g_hash_table_insert (rcpt_hash, (char *) addr, GINT_TO_POINTER (1));
- }
- }
- }
-
- concat_unique_addrs (*cc, to_addrs, rcpt_hash);
- concat_unique_addrs (*cc, cc_addrs, rcpt_hash);
-
- /* promote the first Cc: address to To: if To: is empty */
- if (camel_address_length ((CamelAddress *) *to) == 0 && camel_address_length ((CamelAddress *) *cc) > 0) {
- camel_internet_address_get (*cc, 0, &name, &addr);
- camel_internet_address_add (*to, name, addr);
- camel_address_remove ((CamelAddress *) *cc, 0);
- }
-
- /* if To: is still empty, may we removed duplicates (i.e. ourself), so add the original To if it was set */
- if (camel_address_length((CamelAddress *)*to) == 0
- && (camel_internet_address_get(to_addrs, 0, &name, &addr)
- || camel_internet_address_get(cc_addrs, 0, &name, &addr))) {
- camel_internet_address_add(*to, name, addr);
- }
-
- g_hash_table_destroy (rcpt_hash);
-}
-
-enum {
- ATTRIB_UNKNOWN,
- ATTRIB_CUSTOM,
- ATTRIB_TIMEZONE,
- ATTRIB_STRFTIME,
- ATTRIB_TM_SEC,
- ATTRIB_TM_MIN,
- ATTRIB_TM_24HOUR,
- ATTRIB_TM_12HOUR,
- ATTRIB_TM_MDAY,
- ATTRIB_TM_MON,
- ATTRIB_TM_YEAR,
- ATTRIB_TM_2YEAR,
- ATTRIB_TM_WDAY, /* not actually used */
- ATTRIB_TM_YDAY,
-};
-
-typedef void (* AttribFormatter) (GString *str, const char *attr, CamelMimeMessage *message);
-
-static void
-format_sender (GString *str, const char *attr, CamelMimeMessage *message)
-{
- const CamelInternetAddress *sender;
- const char *name, *addr;
-
- sender = camel_mime_message_get_from (message);
- if (sender != NULL && camel_address_length (CAMEL_ADDRESS (sender)) > 0) {
- camel_internet_address_get (sender, 0, &name, &addr);
- } else {
- name = _("an unknown sender");
- }
-
- if (name && !strcmp (attr, "{SenderName}")) {
- g_string_append (str, name);
- } else if (addr && !strcmp (attr, "{SenderEMail}")) {
- g_string_append (str, addr);
- } else if (name && *name) {
- g_string_append (str, name);
- } else if (addr) {
- g_string_append (str, addr);
- }
-}
-
-static struct {
- const char *name;
- int type;
- struct {
- const char *format; /* strftime or printf format */
- AttribFormatter formatter; /* custom formatter */
- } v;
-} attribvars[] = {
- { "{Sender}", ATTRIB_CUSTOM, { NULL, format_sender } },
- { "{SenderName}", ATTRIB_CUSTOM, { NULL, format_sender } },
- { "{SenderEMail}", ATTRIB_CUSTOM, { NULL, format_sender } },
- { "{AbbrevWeekdayName}", ATTRIB_STRFTIME, { "%a", NULL } },
- { "{WeekdayName}", ATTRIB_STRFTIME, { "%A", NULL } },
- { "{AbbrevMonthName}", ATTRIB_STRFTIME, { "%b", NULL } },
- { "{MonthName}", ATTRIB_STRFTIME, { "%B", NULL } },
- { "{AmPmUpper}", ATTRIB_STRFTIME, { "%p", NULL } },
- { "{AmPmLower}", ATTRIB_STRFTIME, { "%P", NULL } },
- { "{Day}", ATTRIB_TM_MDAY, { "%02d", NULL } }, /* %d 01-31 */
- { "{ Day}", ATTRIB_TM_MDAY, { "% 2d", NULL } }, /* %e 1-31 */
- { "{24Hour}", ATTRIB_TM_24HOUR, { "%02d", NULL } }, /* %H 00-23 */
- { "{12Hour}", ATTRIB_TM_12HOUR, { "%02d", NULL } }, /* %I 00-12 */
- { "{DayOfYear}", ATTRIB_TM_YDAY, { "%d", NULL } }, /* %j 1-366 */
- { "{Month}", ATTRIB_TM_MON, { "%02d", NULL } }, /* %m 01-12 */
- { "{Minute}", ATTRIB_TM_MIN, { "%02d", NULL } }, /* %M 00-59 */
- { "{Seconds}", ATTRIB_TM_SEC, { "%02d", NULL } }, /* %S 00-61 */
- { "{2DigitYear}", ATTRIB_TM_2YEAR, { "%02d", NULL } }, /* %y */
- { "{Year}", ATTRIB_TM_YEAR, { "%04d", NULL } }, /* %Y */
- { "{TimeZone}", ATTRIB_TIMEZONE, { "%+05d", NULL } }
-};
-
-/* Note to translators: this is the attribution string used when quoting messages.
- * each ${Variable} gets replaced with a value. To see a full list of available
- * variables, see em-composer-utils.c:1514 */
-#define ATTRIBUTION _("On ${AbbrevWeekdayName}, ${Year}-${Month}-${Day} at ${24Hour}:${Minute} ${TimeZone}, ${Sender} wrote:")
-
-static char *
-attribution_format (const char *format, CamelMimeMessage *message)
-{
- register const char *inptr;
- const char *start;
- int tzone, len, i;
- char buf[64], *s;
- GString *str;
- struct tm tm;
- time_t date;
- int type;
-
- str = g_string_new ("");
-
- date = camel_mime_message_get_date (message, &tzone);
- /* Convert to UTC */
- date += (tzone / 100) * 60 * 60;
- date += (tzone % 100) * 60;
-
-#ifdef HAVE_GMTIME_R
- gmtime_r (&date, &tm);
-#else
- memcpy (&tm, gmtime (&date), sizeof (struct tm));
-#endif
-
- start = inptr = format;
- while (*inptr != '\0') {
- start = inptr;
- while (*inptr && strncmp (inptr, "${", 2) != 0)
- inptr++;
-
- g_string_append_len (str, start, inptr - start);
-
- if (*inptr == '\0')
- break;
-
- start = ++inptr;
- while (*inptr && *inptr != '}')
- inptr++;
-
- if (*inptr != '}') {
- /* broken translation */
- g_string_append_len (str, "${", 2);
- inptr = start + 1;
- continue;
- }
-
- inptr++;
- len = inptr - start;
- type = ATTRIB_UNKNOWN;
- for (i = 0; i < G_N_ELEMENTS (attribvars); i++) {
- if (!strncmp (attribvars[i].name, start, len)) {
- type = attribvars[i].type;
- break;
- }
- }
-
- switch (type) {
- case ATTRIB_CUSTOM:
- attribvars[i].v.formatter (str, attribvars[i].name, message);
- break;
- case ATTRIB_TIMEZONE:
- g_string_append_printf (str, attribvars[i].v.format, tzone);
- break;
- case ATTRIB_STRFTIME:
- e_utf8_strftime (buf, sizeof (buf), attribvars[i].v.format, &tm);
- g_string_append (str, buf);
- break;
- case ATTRIB_TM_SEC:
- g_string_append_printf (str, attribvars[i].v.format, tm.tm_sec);
- break;
- case ATTRIB_TM_MIN:
- g_string_append_printf (str, attribvars[i].v.format, tm.tm_min);
- break;
- case ATTRIB_TM_24HOUR:
- g_string_append_printf (str, attribvars[i].v.format, tm.tm_hour);
- break;
- case ATTRIB_TM_12HOUR:
- g_string_append_printf (str, attribvars[i].v.format, (tm.tm_hour + 1) % 13);
- break;
- case ATTRIB_TM_MDAY:
- g_string_append_printf (str, attribvars[i].v.format, tm.tm_mday);
- break;
- case ATTRIB_TM_MON:
- g_string_append_printf (str, attribvars[i].v.format, tm.tm_mon + 1);
- break;
- case ATTRIB_TM_YEAR:
- g_string_append_printf (str, attribvars[i].v.format, tm.tm_year + 1900);
- break;
- case ATTRIB_TM_2YEAR:
- g_string_append_printf (str, attribvars[i].v.format, tm.tm_year % 100);
- break;
- case ATTRIB_TM_WDAY:
- /* not actually used */
- g_string_append_printf (str, attribvars[i].v.format, tm.tm_wday);
- break;
- case ATTRIB_TM_YDAY:
- g_string_append_printf (str, attribvars[i].v.format, tm.tm_yday + 1);
- break;
- default:
- /* mis-spelled variable? drop the format argument and continue */
- break;
- }
- }
-
- s = str->str;
- g_string_free (str, FALSE);
-
- return s;
-}
-
-static void
-composer_set_body (EMsgComposer *composer, CamelMimeMessage *message, EMFormat *source)
-{
- char *text, *credits;
- CamelMimePart *part;
- GConfClient *gconf;
- ssize_t len;
-
- gconf = mail_config_get_gconf_client ();
-
- switch (gconf_client_get_int (gconf, "/apps/evolution/mail/format/reply_style", NULL)) {
- case MAIL_CONFIG_REPLY_DO_NOT_QUOTE:
- /* do nothing */
- break;
- case MAIL_CONFIG_REPLY_ATTACH:
- /* attach the original message as an attachment */
- part = mail_tool_make_message_attachment (message);
- e_msg_composer_attach (composer, part);
- camel_object_unref (part);
- break;
- case MAIL_CONFIG_REPLY_QUOTED:
- default:
- /* do what any sane user would want when replying... */
- credits = attribution_format (ATTRIBUTION, message);
- text = em_utils_message_to_html(message, credits, EM_FORMAT_QUOTE_CITE, &len, source);
- g_free (credits);
- e_msg_composer_set_body_text(composer, text, len);
- g_free (text);
- break;
- }
-
- e_msg_composer_drop_editor_undo (composer);
-}
-
-struct _reply_data {
- EMFormat *source;
- int mode;
-};
-
-static void
-reply_to_message(CamelFolder *folder, const char *uid, CamelMimeMessage *message, void *user_data)
-{
- struct _reply_data *rd = user_data;
-
- if (message != NULL)
- em_utils_reply_to_message(folder, uid, message, rd->mode, rd->source);
-
- g_object_unref(rd->source);
- g_free(rd);
-}
-
-/**
- * em_utils_reply_to_message:
- * @folder: optional folder
- * @uid: optional uid
- * @message: message to reply to, optional
- * @mode: reply mode
- * @source: source to inherit view settings from
- *
- * Creates a new composer ready to reply to @message.
- *
- * If @message is NULL then @folder and @uid must be set to the
- * message to be replied to, it will be loaded asynchronously.
- *
- * If @message is non null, then it is used directly, @folder and @uid
- * may be supplied in order to update the message flags once it has
- * been replied to.
- **/
-void
-em_utils_reply_to_message(CamelFolder *folder, const char *uid, CamelMimeMessage *message, int mode, EMFormat *source)
-{
- CamelInternetAddress *to = NULL, *cc = NULL;
- EMsgComposer *composer;
- EAccount *account;
- const char *postto = NULL;
- guint32 flags;
-
- if (folder && uid && message == NULL) {
- struct _reply_data *rd = g_malloc0(sizeof(*rd));
-
- rd->mode = mode;
- rd->source = source;
- g_object_ref(rd->source);
- mail_get_message(folder, uid, reply_to_message, rd, mail_thread_new);
-
- return;
- }
-
- g_return_if_fail(message != NULL);
-
- account = guess_account (message, NULL);
- flags = CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_SEEN;
-
- switch (mode) {
- case REPLY_MODE_SENDER:
- if (folder)
- get_reply_sender (message, &to, &postto);
- else
- get_reply_sender (message, &to, NULL);
- break;
- case REPLY_MODE_LIST:
- flags |= CAMEL_MESSAGE_ANSWERED_ALL;
- if (get_reply_list (message, &to))
- break;
- case REPLY_MODE_ALL:
- flags |= CAMEL_MESSAGE_ANSWERED_ALL;
- if (folder)
- get_reply_all (message, &to, &cc, &postto);
- else
- get_reply_all (message, &to, &cc, NULL);
- break;
- }
-
- composer = reply_get_composer (message, account, to, cc, folder, postto);
- e_msg_composer_add_message_attachments (composer, message, TRUE);
-
- if (to != NULL)
- camel_object_unref (to);
-
- if (cc != NULL)
- camel_object_unref (cc);
-
- composer_set_body (composer, message, source);
-
- em_composer_utils_setup_callbacks (composer, folder, uid, flags, flags, NULL, NULL);
-
- gtk_widget_show (GTK_WIDGET (composer));
- e_msg_composer_unset_changed (composer);
-}
-
-/* Posting replies... */
-
-static void
-post_reply_to_message (CamelFolder *folder, const char *uid, CamelMimeMessage *message, void *user_data)
-{
- /* FIXME: would be nice if this shared more code with reply_get_composer() */
- const char *message_id, *references;
- CamelInternetAddress *to = NULL;
- EDestination **tov = NULL;
- EMsgComposer *composer;
- char *subject, *url;
- EAccount *account;
- guint32 flags;
-
- if (message == NULL)
- return;
-
- account = guess_account (message, folder);
- flags = CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_SEEN;
-
- get_reply_sender (message, &to, NULL);
-
- composer = e_msg_composer_new_with_type (E_MSG_COMPOSER_MAIL_POST);
-
- /* construct the tov/ccv */
- tov = em_utils_camel_address_to_destination (to);
-
- /* Set the subject of the new message. */
- if ((subject = (char *) camel_mime_message_get_subject (message))) {
- if (strncasecmp (subject, "Re: ", 4) != 0)
- subject = g_strdup_printf ("Re: %s", subject);
- else
- subject = g_strdup (subject);
- } else {
- subject = g_strdup ("");
- }
-
- e_msg_composer_set_headers (composer, account ? account->name : NULL, tov, NULL, NULL, subject);
-
- g_free (subject);
-
- url = mail_tools_folder_to_url (folder);
- e_msg_composer_hdrs_set_post_to ((EMsgComposerHdrs *) composer->hdrs, url);
- g_free (url);
-
- /* Add In-Reply-To and References. */
- message_id = camel_medium_get_header (CAMEL_MEDIUM (message), "Message-Id");
- references = camel_medium_get_header (CAMEL_MEDIUM (message), "References");
- if (message_id) {
- char *reply_refs;
-
- e_msg_composer_add_header (composer, "In-Reply-To", message_id);
-
- if (references)
- reply_refs = g_strdup_printf ("%s %s", references, message_id);
- else
- reply_refs = g_strdup (message_id);
-
- e_msg_composer_add_header (composer, "References", reply_refs);
- g_free (reply_refs);
- } else if (references) {
- e_msg_composer_add_header (composer, "References", references);
- }
-
- e_msg_composer_drop_editor_undo (composer);
-
- e_msg_composer_add_message_attachments (composer, message, TRUE);
-
- if (to != NULL)
- camel_object_unref (to);
-
- composer_set_body (composer, message, NULL);
-
- em_composer_utils_setup_callbacks (composer, folder, uid, flags, flags, NULL, NULL);
-
- gtk_widget_show (GTK_WIDGET (composer));
- e_msg_composer_unset_changed (composer);
-}
-
-/**
- * em_utils_post_reply_to_message_by_uid:
- * @folder: folder containing message to reply to
- * @uid: message uid
- * @mode: reply mode
- *
- * Creates a new composer (post mode) ready to reply to the message
- * referenced by @folder and @uid.
- **/
-void
-em_utils_post_reply_to_message_by_uid (CamelFolder *folder, const char *uid)
-{
- g_return_if_fail (CAMEL_IS_FOLDER (folder));
- g_return_if_fail (uid != NULL);
-
- mail_get_message (folder, uid, post_reply_to_message, NULL, mail_thread_new);
-}