From f4cf9af33ccde3142a3011e8b2dbcfb4cbc9ae81 Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Wed, 20 May 2009 16:50:00 +0200 Subject: Use -no-undefined on Linux too There still left two things opened, search for KILL-BONOBO to find them. One is in calendar's Makefile.am, one in composer. --- em-format/em-format-quote.c | 586 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 586 insertions(+) create mode 100644 em-format/em-format-quote.c (limited to 'em-format/em-format-quote.c') diff --git a/em-format/em-format-quote.c b/em-format/em-format-quote.c new file mode 100644 index 0000000000..5503cca916 --- /dev/null +++ b/em-format/em-format-quote.c @@ -0,0 +1,586 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Jeffrey Stedfast + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "em-stripsig-filter.h" +#include "em-format-quote.h" + +struct _EMFormatQuotePrivate { + int dummy; +}; + +static void emfq_format_clone(EMFormat *, CamelFolder *, const char *, CamelMimeMessage *, EMFormat *); +static void emfq_format_error(EMFormat *emf, CamelStream *stream, const char *txt); +static void emfq_format_message(EMFormat *, CamelStream *, CamelMimePart *, const EMFormatHandler *); +static void emfq_format_source(EMFormat *, CamelStream *, CamelMimePart *); +static void emfq_format_attachment(EMFormat *, CamelStream *, CamelMimePart *, const char *, const EMFormatHandler *); + +static void emfq_builtin_init(EMFormatQuoteClass *efhc); + +static gpointer parent_class; + +static void +emfq_init(GObject *o) +{ + EMFormatQuote *emfq =(EMFormatQuote *) o; + + /* we want to convert url's etc */ + emfq->text_html_flags = CAMEL_MIME_FILTER_TOHTML_PRE | CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS + | CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES; +} + +static void +emfq_finalize (GObject *object) +{ + EMFormatQuote *emfq =(EMFormatQuote *) object; + + if (emfq->stream) + camel_object_unref(emfq->stream); + g_free(emfq->credits); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +emfq_base_init(EMFormatQuoteClass *emfqclass) +{ + emfq_builtin_init(emfqclass); +} + +static void +emfq_class_init (EMFormatQuoteClass *class) +{ + GObjectClass *object_class; + EMFormatClass *format_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMFormatQuotePrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->finalize = emfq_finalize; + + format_class = EM_FORMAT_CLASS (class); + format_class->format_clone = emfq_format_clone; + format_class->format_error = emfq_format_error; + format_class->format_source = emfq_format_source; + format_class->format_attachment = emfq_format_attachment; +} + +GType +em_format_quote_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMFormatQuoteClass), + (GBaseInitFunc) emfq_base_init, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) emfq_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMFormatQuote), + 0, /* n_preallocs */ + (GInstanceInitFunc) emfq_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + EM_TYPE_FORMAT, "EMFormatQuote", &type_info, 0); + } + + return type; +} + +EMFormatQuote * +em_format_quote_new (const gchar *credits, + CamelStream *stream, + guint32 flags) +{ + EMFormatQuote *emfq; + + emfq = g_object_new (EM_TYPE_FORMAT_QUOTE, NULL); + + emfq->credits = g_strdup (credits); + emfq->stream = stream; + camel_object_ref (stream); + emfq->flags = flags; + + return emfq; +} + +static void +emfq_format_empty_line(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info) +{ + camel_stream_printf(stream, "
\n"); +} + +static void +emfq_format_clone(EMFormat *emf, CamelFolder *folder, const char *uid, CamelMimeMessage *msg, EMFormat *src) +{ + EMFormatQuote *emfq = (EMFormatQuote *) emf; + const EMFormatHandler *handle; + GConfClient *gconf; + + /* Chain up to parent's format_clone() method. */ + EM_FORMAT_CLASS (parent_class)->format_clone (emf, folder, uid, msg, src); + + gconf = gconf_client_get_default (); + camel_stream_reset(emfq->stream); + if (gconf_client_get_bool(gconf, "/apps/evolution/mail/composer/top_signature", NULL)) + emfq_format_empty_line(emf, emfq->stream, (CamelMimePart *)msg, NULL); + g_object_unref (gconf); + handle = em_format_find_handler(emf, "x-evolution/message/prefix"); + if (handle) + handle->handler(emf, emfq->stream, (CamelMimePart *)msg, handle); + handle = em_format_find_handler(emf, "x-evolution/message/rfc822"); + if (handle) + handle->handler(emf, emfq->stream, (CamelMimePart *)msg, handle); + + camel_stream_flush(emfq->stream); + + g_signal_emit_by_name(emf, "complete"); +} + +static void +emfq_format_error(EMFormat *emf, CamelStream *stream, const char *txt) +{ + /* FIXME: should we even bother writing error text for quoting? probably not... */ +} + +static void +emfq_format_text_header (EMFormatQuote *emfq, CamelStream *stream, const char *label, const char *value, guint32 flags, int is_html) +{ + const char *fmt, *html; + char *mhtml = NULL; + + if (value == NULL) + return; + + while (*value == ' ') + value++; + + if (!is_html) + html = mhtml = camel_text_to_html (value, 0, 0); + else + html = value; + + if (flags & EM_FORMAT_HEADER_BOLD) + fmt = "%s: %s
"; + else + fmt = "%s: %s
"; + + camel_stream_printf (stream, fmt, label, html); + g_free (mhtml); +} + +static char *addrspec_hdrs[] = { + "Sender", "From", "Reply-To", "To", "Cc", "Bcc", + "Resent-Sender", "Resent-from", "Resent-Reply-To", + "Resent-To", "Resent-cc", "Resent-Bcc", NULL +}; + +#if 0 +/* FIXME: include Sender and Resent-* headers too? */ +/* For Translators only: The following strings are used in the header table in the preview pane */ +static char *i18n_hdrs[] = { + N_("From"), N_("Reply-To"), N_("To"), N_("Cc"), N_("Bcc") +}; +#endif + +static void +emfq_format_address (GString *out, struct _camel_header_address *a) +{ + guint32 flags = CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES; + char *name, *mailto, *addr; + + while (a) { + if (a->name) + name = camel_text_to_html (a->name, flags, 0); + else + name = NULL; + + switch (a->type) { + case CAMEL_HEADER_ADDRESS_NAME: + if (name && *name) { + char *real, *mailaddr; + + g_string_append_printf (out, "%s <", name); + /* rfc2368 for mailto syntax and url encoding extras */ + if ((real = camel_header_encode_phrase ((unsigned char *)a->name))) { + mailaddr = g_strdup_printf ("%s <%s>", real, a->v.addr); + g_free (real); + mailto = camel_url_encode (mailaddr, "?=&()"); + g_free (mailaddr); + } else { + mailto = camel_url_encode (a->v.addr, "?=&()"); + } + } else { + mailto = camel_url_encode (a->v.addr, "?=&()"); + } + addr = camel_text_to_html (a->v.addr, flags, 0); + g_string_append_printf (out, "%s", mailto, addr); + g_free (mailto); + g_free (addr); + + if (name && *name) + g_string_append (out, ">"); + break; + case CAMEL_HEADER_ADDRESS_GROUP: + g_string_append_printf (out, "%s: ", name); + emfq_format_address (out, a->v.members); + g_string_append_printf (out, ";"); + break; + default: + g_warning ("Invalid address type"); + break; + } + + g_free (name); + + a = a->next; + if (a) + g_string_append (out, ", "); + } +} + +static void +canon_header_name (char *name) +{ + char *inptr = name; + + /* canonicalise the header name... first letter is + * capitalised and any letter following a '-' also gets + * capitalised */ + + if (*inptr >= 'a' && *inptr <= 'z') + *inptr -= 0x20; + + inptr++; + + while (*inptr) { + if (inptr[-1] == '-' && *inptr >= 'a' && *inptr <= 'z') + *inptr -= 0x20; + else if (*inptr >= 'A' && *inptr <= 'Z') + *inptr += 0x20; + + inptr++; + } +} + +static void +emfq_format_header (EMFormat *emf, CamelStream *stream, CamelMedium *part, const char *namein, guint32 flags, const char *charset) +{ + CamelMimeMessage *msg = (CamelMimeMessage *) part; + EMFormatQuote *emfq = (EMFormatQuote *) emf; + char *name, *buf, *value = NULL; + const char *txt, *label; + gboolean addrspec = FALSE; + int is_html = FALSE; + int i; + + name = g_alloca (strlen (namein) + 1); + strcpy (name, namein); + canon_header_name (name); + + for (i = 0; addrspec_hdrs[i]; i++) { + if (!strcmp (name, addrspec_hdrs[i])) { + addrspec = TRUE; + break; + } + } + + label = _(name); + + if (addrspec) { + struct _camel_header_address *addrs; + GString *html; + + if (!(txt = camel_medium_get_header (part, name))) + return; + + buf = camel_header_unfold (txt); + if (!(addrs = camel_header_address_decode (txt, emf->charset ? emf->charset : emf->default_charset))) { + g_free (buf); + return; + } + + g_free (buf); + + html = g_string_new (""); + emfq_format_address (html, addrs); + camel_header_address_unref (addrs); + txt = value = html->str; + g_string_free (html, FALSE); + flags |= EM_FORMAT_HEADER_BOLD; + is_html = TRUE; + } else if (!strcmp (name, "Subject")) { + txt = camel_mime_message_get_subject (msg); + label = _("Subject"); + flags |= EM_FORMAT_HEADER_BOLD; + } else if (!strcmp (name, "X-Evolution-Mailer")) { /* pseudo-header */ + if (!(txt = camel_medium_get_header (part, "x-mailer"))) + if (!(txt = camel_medium_get_header (part, "user-agent"))) + if (!(txt = camel_medium_get_header (part, "x-newsreader"))) + if (!(txt = camel_medium_get_header (part, "x-mimeole"))) + return; + + txt = value = camel_header_format_ctext (txt, charset); + + label = _("Mailer"); + flags |= EM_FORMAT_HEADER_BOLD; + } else if (!strcmp (name, "Date") || !strcmp (name, "Resent-Date")) { + if (!(txt = camel_medium_get_header (part, name))) + return; + + flags |= EM_FORMAT_HEADER_BOLD; + } else { + txt = camel_medium_get_header (part, name); + buf = camel_header_unfold (txt); + txt = value = camel_header_decode_string (txt, charset); + g_free (buf); + } + + emfq_format_text_header (emfq, stream, label, txt, flags, is_html); + + g_free (value); +} + +static void +emfq_format_headers (EMFormatQuote *emfq, CamelStream *stream, CamelMedium *part) +{ + EMFormat *emf = (EMFormat *) emfq; + CamelContentType *ct; + const char *charset; + EMFormatHeader *h; + + if (!part) + return; + + ct = camel_mime_part_get_content_type ((CamelMimePart *) part); + charset = camel_content_type_param (ct, "charset"); + charset = camel_iconv_charset_name (charset); + + /* dump selected headers */ + h = (EMFormatHeader *) emf->header_list.head; + while (h->next) { + emfq_format_header (emf, stream, part, h->name, h->flags, charset); + h = h->next; + } + + camel_stream_printf(stream, "
\n"); +} + +static void +emfq_format_message_prefix(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info) +{ + EMFormatQuote *emfq = (EMFormatQuote *) emf; + + if (emfq->credits) + camel_stream_printf(stream, "%s
\n", emfq->credits); +} + +static void +emfq_format_message(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info) +{ + EMFormatQuote *emfq = (EMFormatQuote *) emf; + + if (emfq->flags & EM_FORMAT_QUOTE_CITE) + camel_stream_printf(stream, "\n" + "
\n"); + + if (((CamelMimePart *)emf->message) != part) { + camel_stream_printf(stream, "%s
\n", _("-------- Forwarded Message --------")); + emfq_format_headers (emfq, stream, (CamelMedium *)part); + } else if (emfq->flags & EM_FORMAT_QUOTE_HEADERS) + emfq_format_headers (emfq, stream, (CamelMedium *)part); + + em_format_part (emf, stream, part); + + if (emfq->flags & EM_FORMAT_QUOTE_CITE) + camel_stream_write_string(stream, "
"); +} + +static void +emfq_format_source(EMFormat *emf, CamelStream *stream, CamelMimePart *part) +{ + CamelStreamFilter *filtered_stream; + CamelMimeFilter *html_filter; + + filtered_stream = camel_stream_filter_new_with_stream ((CamelStream *) stream); + html_filter = camel_mime_filter_tohtml_new (CAMEL_MIME_FILTER_TOHTML_CONVERT_NL + | CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES + | CAMEL_MIME_FILTER_TOHTML_ESCAPE_8BIT, 0); + camel_stream_filter_add(filtered_stream, html_filter); + camel_object_unref(html_filter); + + em_format_format_text(emf, (CamelStream *)filtered_stream, (CamelDataWrapper *)part); + camel_object_unref(filtered_stream); +} + +static void +emfq_format_attachment(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const char *mime_type, const EMFormatHandler *handle) +{ + if (handle && em_format_is_inline(emf, emf->part_id->str, part, handle)) { + char *text, *html; + + camel_stream_write_string(stream, + "
\n"); + + /* output some info about it */ + text = em_format_describe_part(part, mime_type); + html = camel_text_to_html(text, ((EMFormatQuote *)emf)->text_html_flags & CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0); + camel_stream_write_string(stream, html); + g_free(html); + g_free(text); + + camel_stream_write_string(stream, "
"); + + handle->handler(emf, stream, part, handle); + } +} + +#include +#include +#include +#include + +static void +emfq_text_plain(EMFormatQuote *emfq, CamelStream *stream, CamelMimePart *part, EMFormatHandler *info) +{ + CamelStreamFilter *filtered_stream; + CamelMimeFilter *html_filter; + CamelMimeFilter *sig_strip; + CamelContentType *type; + const char *format; + guint32 rgb = 0x737373, flags; + + if (!part) + return; + + flags = emfq->text_html_flags; + + /* Check for RFC 2646 flowed text. */ + type = camel_mime_part_get_content_type(part); + if (camel_content_type_is(type, "text", "plain") + && (format = camel_content_type_param(type, "format")) + && !g_ascii_strcasecmp(format, "flowed")) + flags |= CAMEL_MIME_FILTER_TOHTML_FORMAT_FLOWED; + + filtered_stream = camel_stream_filter_new_with_stream(stream); + + if (emfq->flags != 0) { + sig_strip = em_stripsig_filter_new (); + camel_stream_filter_add (filtered_stream, sig_strip); + camel_object_unref (sig_strip); + } + + html_filter = camel_mime_filter_tohtml_new(flags, rgb); + camel_stream_filter_add(filtered_stream, html_filter); + camel_object_unref(html_filter); + + em_format_format_text((EMFormat *)emfq, (CamelStream *)filtered_stream, (CamelDataWrapper *)part); + camel_stream_flush((CamelStream *)filtered_stream); + camel_object_unref(filtered_stream); +} + +static void +emfq_text_enriched(EMFormatQuote *emfq, CamelStream *stream, CamelMimePart *part, EMFormatHandler *info) +{ + CamelStreamFilter *filtered_stream; + CamelMimeFilter *enriched; + CamelDataWrapper *dw; + guint32 flags = 0; + + dw = camel_medium_get_content_object((CamelMedium *)part); + + if (!strcmp(info->mime_type, "text/richtext")) { + flags = CAMEL_MIME_FILTER_ENRICHED_IS_RICHTEXT; + camel_stream_write_string(stream, "\n\n"); + } else { + camel_stream_write_string(stream, "\n\n"); + } + + enriched = camel_mime_filter_enriched_new(flags); + filtered_stream = camel_stream_filter_new_with_stream (stream); + camel_stream_filter_add(filtered_stream, enriched); + camel_object_unref(enriched); + + camel_stream_write_string(stream, "


"); + em_format_format_text((EMFormat *)emfq, (CamelStream *)filtered_stream, (CamelDataWrapper *)part); + camel_object_unref(filtered_stream); +} + +static void +emfq_text_html(EMFormat *emf, CamelStream *stream, CamelMimePart *part, EMFormatHandler *info) +{ + camel_stream_write_string(stream, "\n\n"); + em_format_format_text(emf, stream, (CamelDataWrapper *)part); +} + +static void +emfq_ignore(EMFormat *emf, CamelStream *stream, CamelMimePart *part, EMFormatHandler *info) +{ + /* NOOP */ +} + +static EMFormatHandler type_builtin_table[] = { + { "text/plain",(EMFormatFunc)emfq_text_plain }, + { "text/enriched",(EMFormatFunc)emfq_text_enriched }, + { "text/richtext",(EMFormatFunc)emfq_text_enriched }, + { "text/html",(EMFormatFunc)emfq_text_html }, +/* { "multipart/related",(EMFormatFunc)emfq_multipart_related },*/ + { "message/external-body", (EMFormatFunc)emfq_ignore }, + { "multipart/appledouble", (EMFormatFunc)emfq_ignore }, + + /* internal evolution types */ + { "x-evolution/evolution-rss-feed", (EMFormatFunc)emfq_text_html }, + { "x-evolution/message/rfc822", (EMFormatFunc)emfq_format_message }, + { "x-evolution/message/prefix", (EMFormatFunc)emfq_format_message_prefix }, +}; + +static void +emfq_builtin_init(EMFormatQuoteClass *efhc) +{ + int i; + + for (i=0;i