diff options
Diffstat (limited to 'em-format/em-format-quote.c')
-rw-r--r-- | em-format/em-format-quote.c | 792 |
1 files changed, 403 insertions, 389 deletions
diff --git a/em-format/em-format-quote.c b/em-format/em-format-quote.c index c3f75ec14d..4822f115d7 100644 --- a/em-format/em-format-quote.c +++ b/em-format/em-format-quote.c @@ -39,237 +39,73 @@ struct _EMFormatQuotePrivate { gchar *credits; - CamelStream *stream; EMFormatQuoteFlags flags; guint32 text_html_flags; }; static void emfq_builtin_init (EMFormatQuoteClass *efhc); -static gpointer parent_class; - -static void -emfq_dispose (GObject *object) -{ - EMFormatQuotePrivate *priv; - - priv = EM_FORMAT_QUOTE_GET_PRIVATE (object); - - if (priv->stream != NULL) { - g_object_unref (priv->stream); - priv->stream = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -emfq_finalize (GObject *object) -{ - EMFormatQuotePrivate *priv; - - priv = EM_FORMAT_QUOTE_GET_PRIVATE (object); - - g_free (priv->credits); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (parent_class)->finalize (object); -} +static CamelMimePart * decode_inline_parts (CamelMimePart *part, GCancellable *cancellable); -static void -emfq_format_clone (EMFormat *emf, - CamelFolder *folder, - const gchar *uid, - CamelMimeMessage *msg, - EMFormat *src, - GCancellable *cancellable) -{ - EMFormatQuote *emfq = (EMFormatQuote *) emf; - const EMFormatHandler *handle; - GSettings *settings; +static void emfq_parse_text_plain (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable); +static void emfq_parse_text_enriched (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable); +static void emfq_parse_text_html (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable); +static void emfq_parse_attachment (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable); - /* Chain up to parent's format_clone() method. */ - EM_FORMAT_CLASS (parent_class)->format_clone ( - emf, folder, uid, msg, src, cancellable); +static void emfq_write_text_plain (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable); +static void emfq_write_text_enriched (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable); +static void emfq_write_text_html (EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable); - g_seekable_seek ( - G_SEEKABLE (emfq->priv->stream), - 0, G_SEEK_SET, NULL, NULL); - - settings = g_settings_new ("org.gnome.evolution.mail"); - if (g_settings_get_boolean ( - settings, "composer-top-signature")) - camel_stream_write_string ( - emfq->priv->stream, "<br>\n", cancellable, NULL); - g_object_unref (settings); - handle = em_format_find_handler(emf, "x-evolution/message/prefix"); - if (handle) - handle->handler ( - emf, emfq->priv->stream, - CAMEL_MIME_PART (msg), - handle, cancellable, FALSE); - handle = em_format_find_handler(emf, "x-evolution/message/rfc822"); - if (handle) - handle->handler ( - emf, emfq->priv->stream, - CAMEL_MIME_PART (msg), - handle, cancellable, FALSE); - - camel_stream_flush (emfq->priv->stream, cancellable, NULL); - - g_signal_emit_by_name(emf, "complete"); -} - -static void -emfq_format_error (EMFormat *emf, - CamelStream *stream, - const gchar *errmsg) -{ - /* Nothing to do. */ -} +static gpointer parent_class; -static void -emfq_format_source (EMFormat *emf, - CamelStream *stream, - CamelMimePart *part, - GCancellable *cancellable) +/* Decodes inline encoded parts of 'part'. The returned pointer, + * if not NULL, should be unreffed with g_object_unref(). */ +static CamelMimePart * +decode_inline_parts (CamelMimePart *part, + GCancellable *cancellable) { + CamelMultipart *mp; + CamelStream *null; CamelStream *filtered_stream; - CamelMimeFilter *html_filter; + EMInlineFilter *inline_filter; - filtered_stream = camel_stream_filter_new (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 ( - CAMEL_STREAM_FILTER (filtered_stream), html_filter); - g_object_unref (html_filter); + g_return_val_if_fail (part != NULL, NULL); - em_format_format_text ( - emf, filtered_stream, - CAMEL_DATA_WRAPPER (part), cancellable); + null = camel_stream_null_new (); + filtered_stream = camel_stream_filter_new (null); + g_object_unref (null); + inline_filter = em_inline_filter_new ( + camel_mime_part_get_encoding (part), + camel_mime_part_get_content_type (part)); + camel_stream_filter_add ( + CAMEL_STREAM_FILTER (filtered_stream), + CAMEL_MIME_FILTER (inline_filter)); + camel_data_wrapper_decode_to_stream_sync ( + camel_medium_get_content (CAMEL_MEDIUM (part)), + filtered_stream, cancellable, NULL); + camel_stream_close (filtered_stream, cancellable, NULL); g_object_unref (filtered_stream); -} - -static void -emfq_format_attachment (EMFormat *emf, - CamelStream *stream, - CamelMimePart *part, - const gchar *mime_type, - const EMFormatHandler *handle, - GCancellable *cancellable) -{ - EMFormatQuote *emfq = EM_FORMAT_QUOTE (emf); - gchar *text, *html; - - if (!em_format_is_inline (emf, emf->part_id->str, part, handle)) - return; - - camel_stream_write_string ( - stream, "<table border=1 cellspacing=0 cellpadding=0>" - "<tr><td><font size=-1>\n", cancellable, NULL); - - /* output some info about it */ - text = em_format_describe_part (part, mime_type); - html = camel_text_to_html ( - text, emfq->priv->text_html_flags & - CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0); - camel_stream_write_string (stream, html, cancellable, NULL); - g_free (html); - g_free (text); - - camel_stream_write_string ( - stream, "</font></td></tr></table>", cancellable, NULL); - - handle->handler (emf, stream, part, handle, cancellable, FALSE); -} - -static void -emfq_base_init (EMFormatQuoteClass *class) -{ - emfq_builtin_init (class); -} - -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->dispose = emfq_dispose; - 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; -} - -static void -emfq_init (EMFormatQuote *emfq) -{ - emfq->priv = EM_FORMAT_QUOTE_GET_PRIVATE (emfq); - - /* we want to convert url's etc */ - emfq->priv->text_html_flags = - CAMEL_MIME_FILTER_TOHTML_PRE | - CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS | - CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES; -} -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); + if (!em_inline_filter_found_any (inline_filter)) { + g_object_unref (inline_filter); + return NULL; } - return type; -} - -EMFormatQuote * -em_format_quote_new (const gchar *credits, - CamelStream *stream, - EMFormatQuoteFlags flags) -{ - EMFormatQuote *emfq; - - g_return_val_if_fail (CAMEL_IS_STREAM (stream), NULL); - - /* Steam must also be seekable so we can reset its position. */ - g_return_val_if_fail (G_IS_SEEKABLE (stream), NULL); + mp = em_inline_filter_get_multipart (inline_filter); - emfq = g_object_new (EM_TYPE_FORMAT_QUOTE, NULL); + g_object_unref (inline_filter); - emfq->priv->credits = g_strdup (credits); - emfq->priv->stream = g_object_ref (stream); - emfq->priv->flags = flags; + if (mp) { + part = camel_mime_part_new (); + camel_medium_set_content ( + CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (mp)); + g_object_unref (mp); + } else { + g_object_ref (part); + } - return emfq; + return part; } static void @@ -296,18 +132,18 @@ emfq_format_text_header (EMFormatQuote *emfq, if (flags & EM_FORMAT_HEADER_BOLD) g_string_append_printf ( - buffer, "<b>%s</b>: %s<br>", label, html); + buffer, "<b>%s</b>: %s<br>", label, html); else g_string_append_printf ( - buffer, "%s: %s<br>", label, html); + buffer, "%s: %s<br>", label, html); g_free (mhtml); } static const gchar *addrspec_hdrs[] = { - "Sender", "From", "Reply-To", "To", "Cc", "Bcc", - "Resent-Sender", "Resent-from", "Resent-Reply-To", - "Resent-To", "Resent-cc", "Resent-Bcc", NULL + "Sender", "From", "Reply-To", "To", "Cc", "Bcc", + "Resent-Sender", "Resent-from", "Resent-Reply-To", + "Resent-To", "Resent-cc", "Resent-Bcc", NULL }; #if 0 @@ -315,7 +151,7 @@ static const gchar *addrspec_hdrs[] = { /* For Translators only: The following strings are * used in the header table in the preview pane. */ static gchar *i18n_hdrs[] = { - N_("From"), N_("Reply-To"), N_("To"), N_("Cc"), N_("Bcc") + N_("From"), N_("Reply-To"), N_("To"), N_("Cc"), N_("Bcc") }; #endif @@ -337,18 +173,18 @@ emfq_format_address (GString *out, if (name && *name) { gchar *real, *mailaddr; - g_string_append_printf (out, "%s <", name); - /* rfc2368 for mailto syntax and url encoding extras */ + g_string_append_printf (out, "%s <", name); + /* rfc2368 for mailto syntax and url encoding extras */ if ((real = camel_header_encode_phrase ((guchar *) a->name))) { - mailaddr = g_strdup_printf ("%s <%s>", real, a->v.addr); + mailaddr = g_strdup_printf ("%s <%s>", real, a->v.addr); g_free (real); - mailto = camel_url_encode (mailaddr, "?=&()"); + mailto = camel_url_encode (mailaddr, "?=&()"); g_free (mailaddr); } else { - mailto = camel_url_encode (a->v.addr, "?=&()"); + mailto = camel_url_encode (a->v.addr, "?=&()"); } } else { - mailto = camel_url_encode (a->v.addr, "?=&()"); + mailto = camel_url_encode (a->v.addr, "?=&()"); } addr = camel_text_to_html (a->v.addr, flags, 0); g_string_append_printf ( @@ -358,15 +194,15 @@ emfq_format_address (GString *out, g_free (addr); if (name && *name) - g_string_append (out, ">"); + g_string_append (out, ">"); break; case CAMEL_HEADER_ADDRESS_GROUP: - g_string_append_printf (out, "%s: ", name); + g_string_append_printf (out, "%s: ", name); emfq_format_address (out, a->v.members); - g_string_append_printf (out, ";"); + g_string_append_printf (out, ";"); break; default: - g_warning ("Invalid address type"); + g_warning ("Invalid address type"); break; } @@ -374,7 +210,7 @@ emfq_format_address (GString *out, a = a->next; if (a) - g_string_append (out, ", "); + g_string_append (out, ", "); } } @@ -383,20 +219,20 @@ canon_header_name (gchar *name) { gchar *inptr = name; - /* canonicalise the header name... first letter is - * capitalised and any letter following a '-' also gets - * capitalised */ + /* canonicalise the header name... first letter is + * capitalised and any letter following a '-' also gets + * capitalised */ if (g_ascii_islower (*inptr)) - *inptr = g_ascii_toupper (*inptr); + *inptr = g_ascii_toupper (*inptr); inptr++; while (*inptr) { if (inptr[-1] == '-' && g_ascii_islower (*inptr)) - *inptr = g_ascii_toupper (*inptr); + *inptr = g_ascii_toupper (*inptr); else if (g_ascii_isupper (*inptr)) - *inptr = g_ascii_tolower (*inptr); + *inptr = g_ascii_tolower (*inptr); inptr++; } @@ -422,8 +258,8 @@ emfq_format_header (EMFormat *emf, strcpy (name, namein); canon_header_name (name); - /* Never quote Bcc headers */ - if (g_str_equal (name, "Bcc") || g_str_equal (name, "Resent-Bcc")) + /* Never quote Bcc headers */ + if (g_str_equal (name, "Bcc") || g_str_equal (name, "Resent-Bcc")) return; for (i = 0; addrspec_hdrs[i]; i++) { @@ -444,8 +280,8 @@ emfq_format_header (EMFormat *emf, buf = camel_header_unfold (txt); addrs = camel_header_address_decode ( - txt, emf->charset ? - emf->charset : emf->default_charset); + txt, em_format_get_charset (emf) ? + em_format_get_charset (emf) : em_format_get_default_charset (emf)); if (addrs == NULL) { g_free (buf); return; @@ -453,29 +289,29 @@ emfq_format_header (EMFormat *emf, g_free (buf); - html = g_string_new (""); + 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")) { + } else if (!strcmp (name, "Subject")) { txt = camel_mime_message_get_subject (msg); - label = _("Subject"); + 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"))) + } 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"); + label = _("Mailer"); flags |= EM_FORMAT_HEADER_BOLD; - } else if (!strcmp (name, "Date") || !strcmp (name, "Resent-Date")) { + } else if (!strcmp (name, "Date") || !strcmp (name, "Resent-Date")) { if (!(txt = camel_medium_get_header (part, name))) return; @@ -506,10 +342,10 @@ emfq_format_headers (EMFormatQuote *emfq, return; ct = camel_mime_part_get_content_type ((CamelMimePart *) part); - charset = camel_content_type_param (ct, "charset"); + charset = camel_content_type_param (ct, "charset"); charset = camel_iconv_charset_name (charset); - /* dump selected headers */ + /* dump selected headers */ link = g_queue_peek_head_link (&emf->header_list); while (link != NULL) { EMFormatHeader *h = link->data; @@ -518,154 +354,335 @@ emfq_format_headers (EMFormatQuote *emfq, link = g_list_next (link); } - g_string_append (buffer, "<br>\n"); + g_string_append (buffer, "<br>\n"); } static void -emfq_format_message_prefix (EMFormat *emf, - CamelStream *stream, - CamelMimePart *part, - const EMFormatHandler *info, - GCancellable *cancellable, - gboolean is_fallback) +emfq_dispose (GObject *object) { - EMFormatQuote *emfq = (EMFormatQuote *) emf; + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} - if (emfq->priv->credits != NULL) { - camel_stream_write_string ( - stream, emfq->priv->credits, NULL, NULL); - camel_stream_write_string ( - stream, "<br>\n", NULL, NULL); - } +static void +emfq_finalize (GObject *object) +{ + EMFormatQuotePrivate *priv; + + priv = EM_FORMAT_QUOTE_GET_PRIVATE (object); + + g_free (priv->credits); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); } +/******************************************************************************/ static void -emfq_format_message (EMFormat *emf, - CamelStream *stream, - CamelMimePart *part, - const EMFormatHandler *info, - GCancellable *cancellable, - gboolean is_fallback) +emfq_parse_text_plain (EMFormat * emf, + CamelMimePart * part, + GString * part_id, + EMFormatParserInfo * info, + GCancellable * cancellable) { - EMFormatQuote *emfq = (EMFormatQuote *) emf; - GString *buffer; + EMFormatPURI *puri; + CamelMimePart *mp; + gint len; - buffer = g_string_sized_new (1024); + len = part_id->len; + g_string_append (part_id, ".text_plain"); - if (emfq->priv->flags & EM_FORMAT_QUOTE_CITE) - g_string_append ( - buffer, - "<!--+GtkHTML:<DATA class=\"ClueFlow\" " - "key=\"orig\" value=\"1\">-->\n" - "<blockquote type=cite>\n"); + mp = decode_inline_parts (part, cancellable); + if (mp) { - if (((CamelMimePart *) emf->message) != part) { - g_string_append_printf ( - buffer, - "%s</br>\n", - _("-------- Forwarded Message --------")); - emfq_format_headers (emfq, buffer, (CamelMedium *) part); - } else if (emfq->priv->flags & EM_FORMAT_QUOTE_HEADERS) - emfq_format_headers (emfq, buffer, (CamelMedium *) part); + if (CAMEL_IS_MULTIPART (camel_medium_get_content (CAMEL_MEDIUM (mp)))) { + em_format_parse_part (emf, mp, part_id, info, cancellable); + } - camel_stream_write ( - stream, buffer->str, buffer->len, cancellable, NULL); + g_object_unref (mp); + } - em_format_part (emf, stream, part, cancellable); + puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str); + puri->write_func = emfq_write_text_plain; + puri->mime_type = g_strdup ("text/html"); + em_format_add_puri (emf, puri); - if (emfq->priv->flags & EM_FORMAT_QUOTE_CITE) - camel_stream_write_string ( - stream, "</blockquote><!--+GtkHTML:" - "<DATA class=\"ClueFlow\" clear=\"orig\">-->", - cancellable, NULL); + g_string_truncate (part_id, len); } -/* Decodes inline encoded parts of 'part'. The returned pointer, - * if not NULL, should be unreffed with g_object_unref(). */ -static CamelMimePart * -decode_inline_parts (CamelMimePart *part, - GCancellable *cancellable) +static void +emfq_parse_text_html (EMFormat * emf, + CamelMimePart * part, + GString * part_id, + EMFormatParserInfo * info, + GCancellable * cancellable) { - CamelMultipart *mp; - CamelStream *null; - CamelStream *filtered_stream; - EMInlineFilter *inline_filter; + EMFormatPURI *puri; + gint len; - g_return_val_if_fail (part != NULL, NULL); + len = part_id->len; + g_string_append (part_id, ".text_html"); - null = camel_stream_null_new (); - filtered_stream = camel_stream_filter_new (null); - g_object_unref (null); + puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str); + puri->write_func = emfq_write_text_html; + puri->mime_type = g_strdup ("text/html"); + em_format_add_puri (emf, puri); - inline_filter = em_inline_filter_new ( - camel_mime_part_get_encoding (part), - camel_mime_part_get_content_type (part)); - camel_stream_filter_add ( - CAMEL_STREAM_FILTER (filtered_stream), - CAMEL_MIME_FILTER (inline_filter)); - camel_data_wrapper_decode_to_stream_sync ( - camel_medium_get_content (CAMEL_MEDIUM (part)), - filtered_stream, cancellable, NULL); - camel_stream_close (filtered_stream, cancellable, NULL); - g_object_unref (filtered_stream); + g_string_truncate (part_id, len); +} - if (!em_inline_filter_found_any (inline_filter)) { - g_object_unref (inline_filter); - return NULL; +static void +emfq_parse_text_enriched (EMFormat * emf, + CamelMimePart * part, + GString * part_id, + EMFormatParserInfo * info, + GCancellable * cancellable) +{ + EMFormatPURI *puri; + gint len; + + len = part_id->len; + g_string_append (part_id, ".text_enriched"); + + puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str); + puri->write_func = emfq_write_text_enriched; + puri->mime_type = g_strdup ("text/html"); + em_format_add_puri (emf, puri); + + g_string_truncate (part_id, len); +} + +static void +emfq_parse_attachment (EMFormat * emf, + CamelMimePart * part, + GString * part_id, + EMFormatParserInfo * info, + GCancellable * cancellable) +{ + EMFormatPURI *puri; + gint len; + + len = part_id->len; + g_string_append (part_id, ".attachment"); + + puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str); + puri->write_func = emfq_write_text_html; + puri->mime_type = g_strdup ("text/html"); + puri->is_attachment = TRUE; + em_format_add_puri (emf, puri); + + g_string_truncate (part_id, len); +} + +/******************************************************************************/ + +static void +emfq_write_attachment (EMFormat *emf, + EMFormatPURI *puri, + CamelStream *stream, + EMFormatWriterInfo *info, + GCancellable *cancellable) +{ + EMFormatQuote *emfq = EM_FORMAT_QUOTE (emf); + const EMFormatHandler *handler; + gchar *text, *html; + CamelContentType *ct; + const gchar *mime_type; + + ct = camel_mime_part_get_content_type (puri->part); + if (ct) { + mime_type = camel_content_type_simple (ct); + camel_content_type_unref (ct); + } else { + mime_type = "application/octet-stream"; } - mp = em_inline_filter_get_multipart (inline_filter); + handler = em_format_find_handler (emf, mime_type); - g_object_unref (inline_filter); + if (!em_format_is_inline (emf, puri->uri, puri->part, handler)) + return; - if (mp) { - part = camel_mime_part_new (); - camel_medium_set_content ( - CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (mp)); - g_object_unref (mp); + camel_stream_write_string ( + stream, "<table border=1 cellspacing=0 cellpadding=0>" + "<tr><td><font size=-1>\n", cancellable, NULL); + + /* output some info about it */ + text = em_format_describe_part (puri->part, mime_type); + html = camel_text_to_html ( + text, emfq->priv->text_html_flags & + CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0); + camel_stream_write_string (stream, html, cancellable, NULL); + g_free (html); + g_free (text); + + camel_stream_write_string ( + stream, "</font></td></tr></table>", cancellable, NULL); + + if (handler && handler->write_func) + handler->write_func (emf, puri, stream, info, cancellable); +} + +static void +emfq_base_init (EMFormatQuoteClass *klass) +{ + emfq_builtin_init (klass); +} + +static void +emfq_class_init (EMFormatQuoteClass *klass) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (klass); + g_type_class_add_private (klass, sizeof (EMFormatQuotePrivate)); + + object_class = G_OBJECT_CLASS (klass); + object_class->dispose = emfq_dispose; + object_class->finalize = emfq_finalize; +} + +static void +emfq_init (EMFormatQuote *emfq) +{ + emfq->priv = EM_FORMAT_QUOTE_GET_PRIVATE (emfq); + + /* we want to convert url's etc */ + emfq->priv->text_html_flags = + CAMEL_MIME_FILTER_TOHTML_PRE | + CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS | + CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES; +} + +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, + EMFormatQuoteFlags flags) +{ + EMFormatQuote *emfq; + + g_return_val_if_fail (CAMEL_IS_STREAM (stream), NULL); + + /* Steam must also be seekable so we can reset its position. */ + g_return_val_if_fail (G_IS_SEEKABLE (stream), NULL); + + emfq = g_object_new (EM_TYPE_FORMAT_QUOTE, NULL); + + emfq->priv->credits = g_strdup (credits); + emfq->priv->flags = flags; + + return emfq; +} + +void +em_format_quote_write (EMFormatQuote * emfq, + CamelStream * stream, + GCancellable * cancellable) +{ + EMFormat *emf; + GSettings *settings; + GList *iter; + EMFormatWriterInfo info = { 0 }; + + emf = (EMFormat *) emfq; + + g_seekable_seek ( + G_SEEKABLE (stream), + 0, G_SEEK_SET, NULL, NULL); + + settings = g_settings_new ("org.gnome.evolution.mail"); + if (g_settings_get_boolean ( + settings, "composer-top-signature")) + camel_stream_write_string ( + stream, "<br>\n", cancellable, NULL); + g_object_unref (settings); + + if (emfq->priv->credits && *emfq->priv->credits) { + gchar *credits = g_strdup_printf ("%s<br/>", emfq->priv->credits); + camel_stream_write_string (stream, credits, cancellable, NULL); + g_free (credits); } else { - g_object_ref (part); + camel_stream_write_string (stream, "<br/>", cancellable, NULL); } - return part; + if (emfq->priv->flags & EM_FORMAT_QUOTE_CITE) + camel_stream_write_string (stream, + "<!--+GtkHTML:<DATA class=\"ClueFlow\" " + "key=\"orig\" value=\"1\">-->\n" + "<blockquote type=cite>\n", cancellable, NULL); + + for (iter = emf->mail_part_list; iter; iter = iter->next) { + EMFormatPURI *puri = iter->data; + + if (puri->is_attachment || !puri->write_func) + continue; + + puri = iter->data; + + if (emfq->priv->flags & EM_FORMAT_QUOTE_HEADERS) { + GString *buffer = g_string_new (""); + emfq_format_headers (emfq, buffer, (CamelMedium *) puri->part); + camel_stream_write_string (stream, buffer->str, cancellable, NULL); + g_string_free (buffer, TRUE); + } + + puri->write_func (emf, puri, stream, &info, cancellable); + } + + if (emfq->priv->flags & EM_FORMAT_QUOTE_CITE) + camel_stream_write_string ( + stream, "</blockquote><!--+GtkHTML:" + "<DATA class=\"ClueFlow\" clear=\"orig\">-->", + cancellable, NULL); } static void -emfq_text_plain (EMFormat *emf, - CamelStream *stream, - CamelMimePart *part, - const EMFormatHandler *info, - GCancellable *cancellable, - gboolean is_fallback) +emfq_write_text_plain (EMFormat *emf, + EMFormatPURI *puri, + CamelStream *stream, + EMFormatWriterInfo *info, + GCancellable *cancellable) { EMFormatQuote *emfq = EM_FORMAT_QUOTE (emf); CamelStream *filtered_stream; CamelMimeFilter *html_filter; CamelMimeFilter *sig_strip; - CamelMimePart *mp; CamelContentType *type; const gchar *format; guint32 rgb = 0x737373, flags; - if (!part) + if (!puri->part) return; - mp = decode_inline_parts (part, cancellable); - if (mp) { - if (CAMEL_IS_MULTIPART (camel_medium_get_content (CAMEL_MEDIUM (mp)))) { - em_format_part (emf, stream, mp, cancellable); - g_object_unref (mp); - - return; - } - - g_object_unref (mp); - } - flags = emfq->priv->text_html_flags; /* Check for RFC 2646 flowed text. */ - type = camel_mime_part_get_content_type (part); + type = camel_mime_part_get_content_type (puri->part); if (camel_content_type_is(type, "text", "plain") && (format = camel_content_type_param(type, "format")) && !g_ascii_strcasecmp(format, "flowed")) @@ -687,25 +704,32 @@ emfq_text_plain (EMFormat *emf, em_format_format_text ( EM_FORMAT (emfq), filtered_stream, - CAMEL_DATA_WRAPPER (part), cancellable); + CAMEL_DATA_WRAPPER (puri->part), cancellable); camel_stream_flush (filtered_stream, cancellable, NULL); g_object_unref (filtered_stream); } static void -emfq_text_enriched (EMFormat *emf, - CamelStream *stream, - CamelMimePart *part, - const EMFormatHandler *info, - GCancellable *cancellable, - gboolean is_fallback) +emfq_write_text_enriched (EMFormat *emf, + EMFormatPURI *puri, + CamelStream *stream, + EMFormatWriterInfo *info, + GCancellable *cancellable) { CamelStream *filtered_stream; CamelMimeFilter *enriched; guint32 flags = 0; + CamelContentType *ct; + const gchar *mime_type = NULL; + + ct = camel_mime_part_get_content_type (puri->part); + if (ct) { + mime_type = camel_content_type_simple (ct); + camel_content_type_unref (ct); + } - if (g_strcmp0 (info->mime_type, "text/richtext") == 0) { + if (g_strcmp0 (mime_type, "text/richtext") == 0) { flags = CAMEL_MIME_FILTER_ENRICHED_IS_RICHTEXT; camel_stream_write_string ( stream, "\n<!-- text/richtext -->\n", @@ -724,18 +748,17 @@ emfq_text_enriched (EMFormat *emf, camel_stream_write_string (stream, "<br><hr><br>", cancellable, NULL); em_format_format_text ( - emf, filtered_stream, CAMEL_DATA_WRAPPER (part), cancellable); + emf, filtered_stream, CAMEL_DATA_WRAPPER (puri->part), cancellable); camel_stream_flush (filtered_stream, cancellable, NULL); g_object_unref (filtered_stream); } static void -emfq_text_html (EMFormat *emf, - CamelStream *stream, - CamelMimePart *part, - const EMFormatHandler *info, - GCancellable *cancellable, - gboolean is_fallback) +emfq_write_text_html (EMFormat *emf, + EMFormatPURI *puri, + CamelStream *stream, + EMFormatWriterInfo *info, + GCancellable *cancellable) { EMFormatQuotePrivate *priv; @@ -757,40 +780,29 @@ emfq_text_html (EMFormat *emf, em_format_format_text ( emf, filtered_stream, - (CamelDataWrapper *) part, cancellable); + (CamelDataWrapper *) puri->part, cancellable); camel_stream_flush (filtered_stream, cancellable, NULL); g_object_unref (filtered_stream); } else { em_format_format_text ( emf, stream, - (CamelDataWrapper *) part, cancellable); + (CamelDataWrapper *) puri->part, cancellable); } } -static void -emfq_ignore (EMFormat *emf, - CamelStream *stream, - CamelMimePart *part, - const EMFormatHandler *info, - GCancellable *cancellable, - gboolean is_fallback) -{ - /* NOOP */ -} - +/****************************************************************************/ static EMFormatHandler type_builtin_table[] = { - { (gchar *) "text/plain", emfq_text_plain }, - { (gchar *) "text/enriched", emfq_text_enriched }, - { (gchar *) "text/richtext", emfq_text_enriched }, - { (gchar *) "text/html", emfq_text_html }, - { (gchar *) "text/*", emfq_text_plain }, - { (gchar *) "message/external-body", emfq_ignore }, - { (gchar *) "multipart/appledouble", emfq_ignore }, + { (gchar *) "text/plain", emfq_parse_text_plain, emfq_write_text_plain, }, + { (gchar *) "text/enriched", emfq_parse_text_enriched, emfq_write_text_enriched, }, + { (gchar *) "text/richtext", emfq_parse_text_enriched, emfq_write_text_enriched, }, + { (gchar *) "text/html", emfq_parse_text_html, emfq_write_text_html, }, + { (gchar *) "text/*", emfq_parse_text_plain, emfq_write_text_plain, }, + { (gchar *) "message/external-body", em_format_empty_parser, em_format_empty_writer, }, + { (gchar *) "multipart/appledouble", em_format_empty_parser, em_format_empty_writer, }, /* internal evolution types */ - { (gchar *) "x-evolution/evolution-rss-feed", emfq_text_html }, - { (gchar *) "x-evolution/message/rfc822", emfq_format_message }, - { (gchar *) "x-evolution/message/prefix", emfq_format_message_prefix }, + { (gchar *) "x-evolution/evolution-rss-feed", 0, emfq_write_text_html, }, + { (gchar *) "x-evolution/message/attachment", emfq_parse_attachment, emfq_write_attachment, }, }; static void @@ -798,7 +810,9 @@ emfq_builtin_init (EMFormatQuoteClass *efhc) { gint ii; + EMFormatClass *emfc = (EMFormatClass *) efhc; + for (ii = 0; ii < G_N_ELEMENTS (type_builtin_table); ii++) em_format_class_add_handler ( - EM_FORMAT_CLASS (efhc), &type_builtin_table[ii]); + emfc, &type_builtin_table[ii]); } |