diff options
-rw-r--r-- | mail/ChangeLog | 38 | ||||
-rw-r--r-- | mail/mail-callbacks.c | 11 | ||||
-rw-r--r-- | mail/mail-format.c | 189 | ||||
-rw-r--r-- | mail/mail-tools.c | 162 | ||||
-rw-r--r-- | mail/mail-tools.h | 2 | ||||
-rw-r--r-- | mail/mail.h | 3 |
6 files changed, 214 insertions, 191 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog index 683d509a64..91c2f773d2 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,41 @@ +2001-09-06 Dan Winship <danw@ximian.com> + + Fix a bunch of replying/forwarding-related formatting bugs. + + 2749 - Message text not included in reply, but html attachment is + 4294 - "forward inline" should quote the same headers as the + normal mail display + 6100 - Reply to a forwarded email displays email headers + 7255 - Replying to HTML message + 7527 - replying to forwarded message w/ attachments does the wrong + thing + + * mail-format.c (mail_get_message_rfc822): New function to get + message headers and body together, for inline forwards, or replies + containing attached messages. + (mail_get_message_body): Redo this to always return HTML, but keep + the "want_plain" flag, to decide whether to return HTML that looks + like HTML or HTML that looks like plain text. Use + mail_get_message_rfc822 to handle attached message/rfc822 parts. + Don't include the text of vcard or icalendar attachments. Don't + fail to include text parts just because we found an HTML part. + (Since we're always returning HTML now, this doesn't cause + problems any more.) + + * mail-tools.c (mail_tool_quote_message): Simplify greatly. + mail_get_message_body always returns HTML now, and we let it take + care of prepending "> "s too. We then let GtkHTML deal with + converting the HTML to plain text if the user wants to reply in + plain text. + (mail_tool_forward_message): Simplify this a ton too: parts of it + are moved into mail_get_message_rfc822 and parts are now + unnecessary. + + * mail-callbacks.c (do_forward_non_attached): Call + mail_tool_forward_message here always, and let it do the "> " + quoting in the "quoted" case, so that we get the headers too when + forwarding quoted. Related to bug #4294. + 2001-09-05 Dan Winship <danw@ximian.com> * mail-display.c (launch_cb): the "command" of a diff --git a/mail/mail-callbacks.c b/mail/mail-callbacks.c index f3378c2047..dc01bb0f78 100644 --- a/mail/mail-callbacks.c +++ b/mail/mail-callbacks.c @@ -922,19 +922,14 @@ forward_get_composer (CamelMimeMessage *message, const char *subject) static void do_forward_non_attached (CamelFolder *folder, char *uid, CamelMimeMessage *message, void *data) { - char *subject, *text, *title; + char *subject, *text; + MailConfigForwardStyle style = GPOINTER_TO_INT (data); if (!message) return; subject = mail_tool_generate_forward_subject (message); - if (GPOINTER_TO_INT (data) == MAIL_CONFIG_FORWARD_INLINE) { - text = mail_tool_forward_message (message); - } else { - title = e_utf8_from_locale_string (_("Forwarded message:\n")); - text = mail_tool_quote_message (message, title); - g_free (title); - } + text = mail_tool_forward_message (message, style == MAIL_CONFIG_FORWARD_QUOTED); if (text) { EMsgComposer *composer = forward_get_composer (message, subject); diff --git a/mail/mail-format.c b/mail/mail-format.c index 27f4506ad6..4e6dcd474a 100644 --- a/mail/mail-format.c +++ b/mail/mail-format.c @@ -1166,8 +1166,6 @@ handle_application_pgp (CamelMimePart *part, const char *mime_type, buffer = CAMEL_STREAM_MEM (plaintext)->buffer; - /* FIXME: uhm, pgp decrypted data doesn't have to be plaintext - * however this broken pgp method doesn't exactly tell us what it is */ camel_mime_part_set_content (mime_part, buffer->data, buffer->len, "text/plain"); camel_object_unref (CAMEL_OBJECT (plaintext)); } @@ -1292,7 +1290,6 @@ decode_pgp (CamelStream *ciphertext, CamelStream *plaintext, MailDisplay *md) camel_exception_init (&ex); /* FIXME: multipart parts */ - /* another FIXME: this doesn't have to return plaintext you realize... */ if (g_datalist_get_data (md->data, "show_pgp")) { CamelPgpContext *ctx; @@ -1359,9 +1356,6 @@ try_inline_pgp (char *start, MailDisplay *md) mail_html_write (md->html, md->stream, "<hr>"); - /* FIXME: uhm, pgp decrypted data doesn't have to be plaintext - * however, I suppose that since it was 'inline', it probably is */ - ciphertext = camel_stream_mem_new (); camel_stream_write (ciphertext, start, end - start); camel_stream_reset (ciphertext); @@ -2145,32 +2139,146 @@ handle_via_bonobo (CamelMimePart *part, const char *mime_type, return TRUE; } +/** + * mail_get_message_rfc822: + * @message: the message + * @want_plain: whether the caller prefers plain to html + * @cite: whether or not to cite the message text + * + * See mail_get_message_body() below for more details. + * + * Return value: an HTML string representing the text parts of @message. + **/ +static char * +mail_get_message_rfc822 (CamelMimeMessage *message, gboolean want_plain, gboolean cite) +{ + CamelDataWrapper *contents; + GString *retval; + const CamelInternetAddress *cia; + char *text, *citation, *buf, *html; + time_t date_val; + int offset; + + contents = camel_medium_get_content_object (CAMEL_MEDIUM (message)); + text = mail_get_message_body (contents, want_plain, cite); + if (!text) + text = g_strdup (""); + citation = cite ? "> " : ""; + retval = g_string_new (NULL); + + /* Kludge: if text starts with "<PRE>", wrap it around the + * headers too so we won't get a blank line between them for the + * <P> to <PRE> switch. + */ + if (!g_strncasecmp (text, "<pre>", 5)) + g_string_sprintfa (retval, "<PRE>"); + + /* create credits */ + cia = camel_mime_message_get_from (message); + buf = camel_address_format (CAMEL_ADDRESS (cia)); + if (buf) { + html = e_text_to_html (buf, E_TEXT_TO_HTML_CONVERT_NL | E_TEXT_TO_HTML_CONVERT_URLS); + g_string_sprintfa (retval, "%s<b>From:</b> %s<br>", + citation, html); + g_free (html); + g_free (buf); + } + + cia = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_TO); + buf = camel_address_format (CAMEL_ADDRESS (cia)); + if (buf) { + html = e_text_to_html (buf, E_TEXT_TO_HTML_CONVERT_NL | E_TEXT_TO_HTML_CONVERT_URLS); + g_string_sprintfa (retval, "%s<b>To:</b> %s<br>", + citation, html); + g_free (html); + g_free (buf); + } + + cia = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_CC); + buf = camel_address_format (CAMEL_ADDRESS (cia)); + if (buf) { + html = e_text_to_html (buf, E_TEXT_TO_HTML_CONVERT_NL | E_TEXT_TO_HTML_CONVERT_URLS); + g_string_sprintfa (retval, "%s<b>Cc:</b> %s<br>", + citation, html); + g_free (html); + g_free (buf); + } + + buf = (char *) camel_mime_message_get_subject (message); + if (buf) { + html = e_text_to_html (buf, E_TEXT_TO_HTML_CONVERT_NL | E_TEXT_TO_HTML_CONVERT_URLS); + g_string_sprintfa (retval, "%s<b>Subject:</b> %s<br>", + citation, html); + g_free (html); + } + + date_val = camel_mime_message_get_date (message, &offset); + buf = header_format_date (date_val, offset); + html = e_text_to_html (buf, E_TEXT_TO_HTML_CONVERT_NL | E_TEXT_TO_HTML_CONVERT_URLS); + g_string_sprintfa (retval, "%s<b>Date:</b> %s<br>", citation, html); + g_free (html); + + if (!g_strncasecmp (text, "<pre>", 5)) + g_string_sprintfa (retval, "%s<br>%s", citation, text + 5); + else + g_string_sprintfa (retval, "%s<br>%s", citation, text); + g_free (text); + + buf = retval->str; + g_string_free (retval, FALSE); + return buf; +} + +/** + * mail_get_message_body: + * @data: the message or mime part content + * @want_plain: whether the caller prefers plain to html + * @cite: whether or not to cite the message text + * + * This creates an HTML string representing @data. If @want_plain is %TRUE, + * it will be an HTML string that looks like a text/plain representation + * of @data (but it will still be HTML). + * + * If @cite is %TRUE, the message will be cited as a reply, using "> "s. + * + * Return value: the HTML string, which the caller must free, or + * %NULL if @data doesn't include any data which should be forwarded or + * replied to. + **/ char * -mail_get_message_body (CamelDataWrapper *data, gboolean want_plain, gboolean *is_html) +mail_get_message_body (CamelDataWrapper *data, gboolean want_plain, gboolean cite) { CamelMultipart *mp; CamelMimePart *subpart; int i, nparts; - char *subtext, *old; - const char *boundary; + char *subtext, *old, *div; char *text = NULL; CamelContentType *mime_type; - - /* We only include text, message, and multipart bodies. */ + mime_type = camel_data_wrapper_get_mime_type_field (data); - - /* FIXME: This is wrong. We don't want to include large - * images. But if we don't do it this way, we don't get - * the headers... + + /* If it is message/rfc822 or message/news, extract the + * important headers and recursively process the body. */ - if (header_content_type_is (mime_type, "message", "*")) { - *is_html = FALSE; - return get_data_wrapper_text (data); - } - - if (header_content_type_is (mime_type, "text", "*")) { - *is_html = header_content_type_is (mime_type, "text", "html"); - return get_data_wrapper_text (data); + if (header_content_type_is (mime_type, "message", "rfc822") || + header_content_type_is (mime_type, "message", "news")) + return mail_get_message_rfc822 (CAMEL_MIME_MESSAGE (data), want_plain, cite); + + /* If it's a vcard or icalendar, ignore it. */ + if (header_content_type_is (mime_type, "text", "x-vcard") || + header_content_type_is (mime_type, "text", "calendar")) + return NULL; + + /* Get the body data for other text/ or message/ types */ + if (header_content_type_is (mime_type, "text", "*") || + header_content_type_is (mime_type, "message", "*")) { + text = get_data_wrapper_text (data); + if (text && !header_content_type_is (mime_type, "text", "html")) { + char *html = e_text_to_html (text, E_TEXT_TO_HTML_PRE | (cite ? E_TEXT_TO_HTML_CITE : 0)); + g_free (text); + text = html; + } + return text; } /* If it's not message and it's not text, and it's not @@ -2188,38 +2296,31 @@ mail_get_message_body (CamelDataWrapper *data, gboolean want_plain, gboolean *is if (!subpart) return NULL; - data = camel_medium_get_content_object ( - CAMEL_MEDIUM (subpart)); - return mail_get_message_body (data, want_plain, is_html); + data = camel_medium_get_content_object (CAMEL_MEDIUM (subpart)); + return mail_get_message_body (data, want_plain, cite); } + /* Otherwise, concatenate all the parts that we can. */ + if (want_plain) { + if (cite) + div = "<br>\n> ----<br>\n> <br>\n"; + else + div = "<br>\n----<br>\n<br>\n"; + } else + div = "<br><hr><br>"; + nparts = camel_multipart_get_number (mp); - - /* Otherwise, concatenate all the parts that we can. If we find - * an HTML part in there though, return just that: We don't want - * to deal with merging HTML and non-HTML parts. - */ - boundary = camel_multipart_get_boundary (mp); for (i = 0; i < nparts; i++) { subpart = camel_multipart_get_part (mp, i); - if (!mail_part_is_inline (subpart)) - continue; - - data = camel_medium_get_content_object ( - CAMEL_MEDIUM (subpart)); - subtext = mail_get_message_body (data, want_plain, is_html); + data = camel_medium_get_content_object (CAMEL_MEDIUM (subpart)); + subtext = mail_get_message_body (data, want_plain, cite); if (!subtext) continue; - if (*is_html) { - g_free (text); - return subtext; - } if (text) { old = text; - text = g_strdup_printf ("%s\n--%s\n%s", old, - boundary, subtext); + text = g_strdup_printf ("%s%s%s", old, div, subtext); g_free (subtext); g_free (old); } else diff --git a/mail/mail-tools.c b/mail/mail-tools.c index 56575ef4b1..45d5a45a5e 100644 --- a/mail/mail-tools.c +++ b/mail/mail-tools.c @@ -386,12 +386,15 @@ gchar * mail_tool_quote_message (CamelMimeMessage *message, const char *fmt, ...) { CamelDataWrapper *contents; - gboolean want_plain, is_html; + gboolean want_plain; gchar *text; want_plain = !mail_config_get_send_html (); contents = camel_medium_get_content_object (CAMEL_MEDIUM (message)); - text = mail_get_message_body (contents, want_plain, &is_html); + /* We pass "want_plain" for "cite", since if it's HTML, we'll + * do the citing ourself below. + */ + text = mail_get_message_body (contents, want_plain, want_plain); /* Set the quoted reply text. */ if (text) { @@ -406,68 +409,15 @@ mail_tool_quote_message (CamelMimeMessage *message, const char *fmt, ...) va_end (ap); } - if (is_html) { - ret_text = g_strdup_printf ("%s<!--+GtkHTML:<DATA class=\"ClueFlow\" key=\"orig\" value=\"1\">-->" - "<blockquote><i><font color=\"%06x\">\n%s\n" - "</font></i></blockquote>" - "<!--+GtkHTML:<DATA class=\"ClueFlow\" clear=\"orig\">-->", - credits ? credits : "", - mail_config_get_citation_color (), text); - } else { - gchar *s, *d, *quoted_text, *orig_text; - gint lines, len; - - /* Count the number of lines in the body. If - * the text ends with a \n, this will be one - * too high, but that's ok. Allocate enough - * space for the text and the "> "s. - */ - for (s = text, lines = 0; s; s = strchr (s + 1, '\n')) - lines++; - - /* offset is the size of the credits, strlen (text) - * covers the body, lines * 2 does the "> "s, and - * the last +2 covers the final "\0", plus an extra - * "\n" in case text doesn't end with one. - */ - quoted_text = g_malloc (strlen (text) + lines * 2 + 2); - - s = text; - d = quoted_text; - - /* Copy text to quoted_text line by line, - * prepending "> ". - */ - while (1) { - len = strcspn (s, "\n"); - if (len == 0 && !*s) - break; - if (!strncmp ("-- \n", s, 4)) - break; - sprintf (d, "> %.*s\n", len, s); - s += len; - if (!*s++) - break; - d += len + 3; - } - *d = '\0'; - - /* Now convert that to HTML. */ - orig_text = e_text_to_html_full (quoted_text, E_TEXT_TO_HTML_PRE - | (mail_config_get_citation_highlight () - ? E_TEXT_TO_HTML_MARK_CITATION : 0), - mail_config_get_citation_color ()); - g_free (quoted_text); - ret_text = g_strdup_printf ("%s<!--+GtkHTML:<DATA class=\"ClueFlow\" key=\"orig\" value=\"1\">-->" - "%s" - "<!--+GtkHTML:<DATA class=\"ClueFlow\" clear=\"orig\">-->", - credits ? credits : "", - orig_text); - g_free (orig_text); - } - + ret_text = g_strdup_printf ("%s<!--+GtkHTML:<DATA class=\"ClueFlow\" key=\"orig\" value=\"1\">-->" + "<font color=\"%06x\">\n%s%s%s</font>" + "<!--+GtkHTML:<DATA class=\"ClueFlow\" clear=\"orig\">-->", + credits ? credits : "", + mail_config_get_citation_color (), + want_plain ? "" : "<blockquote><i>", + text, + want_plain ? "" : "</i></blockquote>"); g_free (text); - return ret_text; } @@ -476,82 +426,22 @@ mail_tool_quote_message (CamelMimeMessage *message, const char *fmt, ...) /** * mail_tool_forward_message: - * @message: mime message to quote + * @message: mime message to forward + * @quoted: whether to forwarded it quoted (%TRUE) or inline (%FALSE) * * Returns an allocated buffer containing the forwarded message. */ gchar * -mail_tool_forward_message (CamelMimeMessage *message) +mail_tool_forward_message (CamelMimeMessage *message, gboolean quoted) { - CamelDataWrapper *contents; - gboolean want_plain, is_html; - XEvolution *xev; - gchar *text; - - xev = mail_tool_remove_xevolution_headers (message); - - want_plain = !mail_config_get_send_html (); - contents = camel_medium_get_content_object (CAMEL_MEDIUM (message)); - text = mail_get_message_body (contents, want_plain, &is_html); - - mail_tool_restore_xevolution_headers (message, xev); - mail_tool_destroy_xevolution (xev); - - /* Set the quoted reply text. */ - if (text) { - gchar *ret_text, *credits = NULL; - const CamelInternetAddress *cia; - char *buf, *from, *to, *subject; - char *title; - - /* create credits */ - cia = camel_mime_message_get_from (message); - buf = camel_address_format (CAMEL_ADDRESS (cia)); - if (buf) { - from = e_text_to_html (buf, E_TEXT_TO_HTML_CONVERT_NL | E_TEXT_TO_HTML_CONVERT_URLS); - g_free (buf); - } else - from = NULL; - - cia = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_TO); - buf = camel_address_format (CAMEL_ADDRESS (cia)); - if (buf) { - to = e_text_to_html (buf, E_TEXT_TO_HTML_CONVERT_NL | E_TEXT_TO_HTML_CONVERT_URLS); - g_free (buf); - } else - to = NULL; - - buf = (char *) camel_mime_message_get_subject (message); - if (buf) - subject = e_text_to_html (buf, E_TEXT_TO_HTML_CONVERT_NL | E_TEXT_TO_HTML_CONVERT_URLS); - else - subject = ""; - - title = e_utf8_from_locale_string (_("Forwarded Message")); - credits = g_strdup_printf ("-----%s-----<br>" - "<b>From:</b> %s<br>" - "<b>To:</b> %s<br>" - "<b>Subject:</b> %s<br>", - title, from ? from : "", - to ? to : "", subject); - g_free (title); - g_free (from); - g_free (to); - - if (!is_html) { - /* Now convert that to HTML. */ - ret_text = e_text_to_html (text, E_TEXT_TO_HTML_PRE); - g_free (text); - text = ret_text; - } - - ret_text = g_strdup_printf ("%s<br>%s\n", credits, text); - - g_free (credits); - g_free (text); - - return ret_text; - } - - return NULL; + gchar *title, *body, *ret; + + body = mail_get_message_body (CAMEL_DATA_WRAPPER (message), + !mail_config_get_send_html (), + quoted); + title = e_utf8_from_locale_string (_("Forwarded Message")); + ret = g_strdup_printf ("-----%s-----<br>%s", title, body ? body : ""); + g_free (title); + g_free (body); + return ret; } diff --git a/mail/mail-tools.h b/mail/mail-tools.h index 98e68e6920..bcae822001 100644 --- a/mail/mail-tools.h +++ b/mail/mail-tools.h @@ -87,6 +87,6 @@ mail_lookup_url_table (CamelMimeMessage *mime_message); gchar *mail_tool_quote_message (CamelMimeMessage *message, const char *fmt, ...); -gchar *mail_tool_forward_message (CamelMimeMessage *message); +gchar *mail_tool_forward_message (CamelMimeMessage *message, gboolean quoted); #endif diff --git a/mail/mail.h b/mail/mail.h index b8f96739b1..6e13d84f66 100644 --- a/mail/mail.h +++ b/mail/mail.h @@ -61,8 +61,7 @@ gboolean mail_part_is_inline (CamelMimePart *part); gboolean mail_part_is_displayed_inline (CamelMimePart *part, MailDisplay *md); void mail_part_toggle_displayed (CamelMimePart *part, MailDisplay *md); -char *mail_get_message_body (CamelDataWrapper *data, gboolean want_plain, - gboolean *is_html); +char *mail_get_message_body (CamelDataWrapper *data, gboolean want_plain, gboolean cite); /* mail-identify */ char *mail_identify_mime_part (CamelMimePart *part, MailDisplay *md); |