summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/mime/src/mimetpla.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/mime/src/mimetpla.cpp')
-rw-r--r--comm/mailnews/mime/src/mimetpla.cpp409
1 files changed, 409 insertions, 0 deletions
diff --git a/comm/mailnews/mime/src/mimetpla.cpp b/comm/mailnews/mime/src/mimetpla.cpp
new file mode 100644
index 0000000000..081d7951a4
--- /dev/null
+++ b/comm/mailnews/mime/src/mimetpla.cpp
@@ -0,0 +1,409 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mimetpla.h"
+#include "mimebuf.h"
+#include "prmem.h"
+#include "plstr.h"
+#include "mozITXTToHTMLConv.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+#include "nsMimeStringResources.h"
+#include "mimemoz2.h"
+#include "nsIPrefBranch.h"
+#include "prprf.h"
+#include "nsMsgI18N.h"
+
+#define MIME_SUPERCLASS mimeInlineTextClass
+MimeDefClass(MimeInlineTextPlain, MimeInlineTextPlainClass,
+ mimeInlineTextPlainClass, &MIME_SUPERCLASS);
+
+static int MimeInlineTextPlain_parse_begin(MimeObject*);
+static int MimeInlineTextPlain_parse_line(const char*, int32_t, MimeObject*);
+static int MimeInlineTextPlain_parse_eof(MimeObject*, bool);
+
+static int MimeInlineTextPlainClassInitialize(MimeInlineTextPlainClass* clazz) {
+ MimeObjectClass* oclass = (MimeObjectClass*)clazz;
+ NS_ASSERTION(!oclass->class_initialized, "class not initialized");
+ oclass->parse_begin = MimeInlineTextPlain_parse_begin;
+ oclass->parse_line = MimeInlineTextPlain_parse_line;
+ oclass->parse_eof = MimeInlineTextPlain_parse_eof;
+ return 0;
+}
+
+extern "C" void MimeTextBuildPrefixCSS(
+ int32_t quotedSizeSetting, // mail.quoted_size
+ int32_t quotedStyleSetting, // mail.quoted_style
+ nsACString& citationColor, // mail.citation_color
+ nsACString& style) {
+ switch (quotedStyleSetting) {
+ case 0: // regular
+ break;
+ case 1: // bold
+ style.AppendLiteral("font-weight: bold; ");
+ break;
+ case 2: // italic
+ style.AppendLiteral("font-style: italic; ");
+ break;
+ case 3: // bold-italic
+ style.AppendLiteral("font-weight: bold; font-style: italic; ");
+ break;
+ }
+
+ switch (quotedSizeSetting) {
+ case 0: // regular
+ break;
+ case 1: // large
+ style.AppendLiteral("font-size: large; ");
+ break;
+ case 2: // small
+ style.AppendLiteral("font-size: small; ");
+ break;
+ }
+
+ if (!citationColor.IsEmpty()) {
+ style += "color: ";
+ style += citationColor;
+ style += ';';
+ }
+}
+
+static int MimeInlineTextPlain_parse_begin(MimeObject* obj) {
+ int status = 0;
+ bool quoting =
+ (obj->options &&
+ (obj->options->format_out == nsMimeOutput::nsMimeMessageQuoting ||
+ obj->options->format_out ==
+ nsMimeOutput::nsMimeMessageBodyQuoting)); // The output will be
+ // inserted in the
+ // composer as quotation
+ bool plainHTML =
+ quoting || (obj->options && (obj->options->format_out ==
+ nsMimeOutput::nsMimeMessageSaveAs));
+ // Just good(tm) HTML. No reliance on CSS.
+ bool rawPlainText =
+ obj->options &&
+ (obj->options->format_out == nsMimeOutput::nsMimeMessageFilterSniffer ||
+ obj->options->format_out == nsMimeOutput::nsMimeMessageAttach);
+
+ status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_begin(obj);
+ if (status < 0) return status;
+
+ if (!obj->output_p) return 0;
+
+ if (obj->options && obj->options->write_html_p && obj->options->output_fn) {
+ MimeInlineTextPlain* text = (MimeInlineTextPlain*)obj;
+ text->mCiteLevel = 0;
+
+ // Get the prefs
+
+ // Quoting
+ text->mBlockquoting = true; // mail.quoteasblock
+
+ // Viewing
+ text->mQuotedSizeSetting = 0; // mail.quoted_size
+ text->mQuotedStyleSetting = 0; // mail.quoted_style
+ text->mCitationColor.Truncate(); // mail.citation_color
+ text->mStripSig = true; // mail.strip_sig_on_reply
+ bool graphicalQuote = true; // mail.quoted_graphical
+
+ nsIPrefBranch* prefBranch = GetPrefBranch(obj->options);
+ if (prefBranch) {
+ prefBranch->GetIntPref("mail.quoted_size", &(text->mQuotedSizeSetting));
+ prefBranch->GetIntPref("mail.quoted_style", &(text->mQuotedStyleSetting));
+ prefBranch->GetCharPref("mail.citation_color", text->mCitationColor);
+ prefBranch->GetBoolPref("mail.strip_sig_on_reply", &(text->mStripSig));
+ prefBranch->GetBoolPref("mail.quoted_graphical", &graphicalQuote);
+ prefBranch->GetBoolPref("mail.quoteasblock", &(text->mBlockquoting));
+ }
+
+ if (!rawPlainText) {
+ // Get font
+ // only used for viewing (!plainHTML)
+ nsAutoCString fontstyle;
+ nsAutoCString fontLang; // langgroup of the font
+
+ // generic font-family name ( -moz-fixed for fixed font and NULL for
+ // variable font ) is sufficient now that bug 105199 has been fixed.
+
+ if (!obj->options->variable_width_plaintext_p)
+ fontstyle = "font-family: -moz-fixed";
+
+ if (nsMimeOutput::nsMimeMessageBodyDisplay == obj->options->format_out ||
+ nsMimeOutput::nsMimeMessagePrintOutput == obj->options->format_out) {
+ int32_t fontSize; // default font size
+ int32_t fontSizePercentage; // size percentage
+ nsresult rv =
+ GetMailNewsFont(obj, !obj->options->variable_width_plaintext_p,
+ &fontSize, &fontSizePercentage, fontLang);
+ if (NS_SUCCEEDED(rv)) {
+ if (!fontstyle.IsEmpty()) {
+ fontstyle += "; ";
+ }
+ fontstyle += "font-size: ";
+ fontstyle.AppendInt(fontSize);
+ fontstyle += "px;";
+ }
+ }
+
+ // Opening <div>. We currently have to add formatting here. :-(
+ nsAutoCString openingDiv;
+ if (!quoting)
+ /* 4.x' editor can't break <div>s (e.g. to interleave comments).
+ We'll add the class to the <blockquote type=cite> later. */
+ {
+ openingDiv = "<div class=\"moz-text-plain\"";
+ if (!plainHTML) {
+ if (obj->options->wrap_long_lines_p)
+ openingDiv += " wrap=true";
+ else
+ openingDiv += " wrap=false";
+
+ if (graphicalQuote)
+ openingDiv += " graphical-quote=true";
+ else
+ openingDiv += " graphical-quote=false";
+
+ if (!fontstyle.IsEmpty()) {
+ openingDiv += " style=\"";
+ openingDiv += fontstyle;
+ openingDiv += '\"';
+ }
+ if (!fontLang.IsEmpty()) {
+ openingDiv += " lang=\"";
+ openingDiv += fontLang;
+ openingDiv += '\"';
+ }
+ }
+ openingDiv += "><pre wrap class=\"moz-quote-pre\">\n";
+ } else
+ openingDiv = "<pre wrap class=\"moz-quote-pre\">\n";
+
+ /* text/plain objects always have separators before and after them.
+ Note that this is not the case for text/enriched objects. */
+ status = MimeObject_write_separator(obj);
+ if (status < 0) return status;
+
+ status =
+ MimeObject_write(obj, openingDiv.get(), openingDiv.Length(), true);
+ if (status < 0) return status;
+ }
+ }
+
+ return 0;
+}
+
+static int MimeInlineTextPlain_parse_eof(MimeObject* obj, bool abort_p) {
+ int status;
+
+ // Has this method already been called for this object?
+ // In that case return.
+ if (obj->closed_p) return 0;
+
+ nsCString citationColor;
+ MimeInlineTextPlain* text = (MimeInlineTextPlain*)obj;
+ if (text && !text->mCitationColor.IsEmpty())
+ citationColor = text->mCitationColor;
+
+ bool quoting =
+ (obj->options &&
+ (obj->options->format_out == nsMimeOutput::nsMimeMessageQuoting ||
+ obj->options->format_out ==
+ nsMimeOutput::nsMimeMessageBodyQuoting)); // see above
+
+ bool rawPlainText =
+ obj->options &&
+ (obj->options->format_out == nsMimeOutput::nsMimeMessageFilterSniffer ||
+ obj->options->format_out == nsMimeOutput::nsMimeMessageAttach);
+
+ /* Run parent method first, to flush out any buffered data. */
+ status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p);
+ if (status < 0) return status;
+
+ if (!obj->output_p) return 0;
+
+ if (obj->options && obj->options->write_html_p && obj->options->output_fn &&
+ !abort_p && !rawPlainText) {
+ MimeInlineTextPlain* text = (MimeInlineTextPlain*)obj;
+ if (text->mIsSig && !quoting) {
+ status = MimeObject_write(obj, "</div>", 6, false); // .moz-txt-sig
+ if (status < 0) return status;
+ }
+ status = MimeObject_write(obj, "</pre>", 6, false);
+ if (status < 0) return status;
+ if (!quoting) {
+ status = MimeObject_write(obj, "</div>", 6, false);
+ // .moz-text-plain
+ if (status < 0) return status;
+ }
+
+ /* text/plain objects always have separators before and after them.
+ Note that this is not the case for text/enriched objects.
+ */
+ status = MimeObject_write_separator(obj);
+ if (status < 0) return status;
+ }
+
+ return 0;
+}
+
+static int MimeInlineTextPlain_parse_line(const char* line, int32_t length,
+ MimeObject* obj) {
+ int status;
+ bool quoting =
+ (obj->options &&
+ (obj->options->format_out == nsMimeOutput::nsMimeMessageQuoting ||
+ obj->options->format_out ==
+ nsMimeOutput::nsMimeMessageBodyQuoting)); // see above
+ bool plainHTML =
+ quoting || (obj->options && obj->options->format_out ==
+ nsMimeOutput::nsMimeMessageSaveAs);
+ // see above
+
+ bool rawPlainText =
+ obj->options &&
+ (obj->options->format_out == nsMimeOutput::nsMimeMessageFilterSniffer ||
+ obj->options->format_out == nsMimeOutput::nsMimeMessageAttach);
+
+ // this routine gets called for every line of data that comes through the
+ // mime converter. It's important to make sure we are efficient with
+ // how we allocate memory in this routine. be careful if you go to add
+ // more to this routine.
+
+ NS_ASSERTION(length > 0, "zero length");
+ if (length <= 0) return 0;
+
+ mozITXTToHTMLConv* conv = GetTextConverter(obj->options);
+ MimeInlineTextPlain* text = (MimeInlineTextPlain*)obj;
+
+ bool skipConversion = !conv || rawPlainText ||
+ (obj->options && obj->options->force_user_charset);
+
+ char* mailCharset = NULL;
+ nsresult rv;
+
+ if (!skipConversion) {
+ nsDependentCSubstring inputStr(line, length);
+ nsAutoString lineSourceStr;
+
+ // For 'SaveAs', |line| is in |mailCharset|.
+ // convert |line| to UTF-16 before 'html'izing (calling ScanTXT())
+ if (obj->options->format_out ==
+ nsMimeOutput::nsMimeMessageSaveAs) { // Get the mail charset of this
+ // message.
+ MimeInlineText* inlinetext = (MimeInlineText*)obj;
+ if (!inlinetext->initializeCharset)
+ ((MimeInlineTextClass*)&mimeInlineTextClass)->initialize_charset(obj);
+ mailCharset = inlinetext->charset;
+ if (mailCharset && *mailCharset) {
+ rv = nsMsgI18NConvertToUnicode(nsDependentCString(mailCharset),
+ inputStr, lineSourceStr);
+ NS_ENSURE_SUCCESS(rv, -1);
+ } else // this probably never happens ...
+ CopyUTF8toUTF16(inputStr, lineSourceStr);
+ } else // line is in UTF-8
+ CopyUTF8toUTF16(inputStr, lineSourceStr);
+
+ nsAutoCString prefaceResultStr; // Quoting stuff before the real text
+
+ // Recognize quotes
+ uint32_t oldCiteLevel = text->mCiteLevel;
+ uint32_t logicalLineStart = 0;
+ rv = conv->CiteLevelTXT(lineSourceStr.get(), &logicalLineStart,
+ &(text->mCiteLevel));
+ NS_ENSURE_SUCCESS(rv, -1);
+
+ // Find out, which recognitions to do
+ uint32_t whattodo = obj->options->whattodo;
+ if (plainHTML) {
+ if (quoting)
+ whattodo = 0; // This is done on Send. Don't do it twice.
+ else
+ whattodo = whattodo & ~mozITXTToHTMLConv::kGlyphSubstitution;
+ /* Do recognition for the case, the result is viewed in
+ Mozilla, but not GlyphSubstitution, because other UAs
+ might not be able to display the glyphs. */
+ if (!text->mBlockquoting) text->mCiteLevel = 0;
+ }
+
+ // Write blockquote
+ if (text->mCiteLevel > oldCiteLevel) {
+ prefaceResultStr += "</pre>";
+ for (uint32_t i = 0; i < text->mCiteLevel - oldCiteLevel; i++) {
+ nsAutoCString style;
+ MimeTextBuildPrefixCSS(text->mQuotedSizeSetting,
+ text->mQuotedStyleSetting, text->mCitationColor,
+ style);
+ if (!plainHTML && !style.IsEmpty()) {
+ prefaceResultStr += "<blockquote type=cite style=\"";
+ prefaceResultStr += style;
+ prefaceResultStr += "\">";
+ } else
+ prefaceResultStr += "<blockquote type=cite>";
+ }
+ prefaceResultStr += "<pre wrap class=\"moz-quote-pre\">\n";
+ } else if (text->mCiteLevel < oldCiteLevel) {
+ prefaceResultStr += "</pre>";
+ for (uint32_t i = 0; i < oldCiteLevel - text->mCiteLevel; i++)
+ prefaceResultStr += "</blockquote>";
+ prefaceResultStr += "<pre wrap class=\"moz-quote-pre\">\n";
+ }
+
+ // Write plain text quoting tags
+ if (logicalLineStart != 0 && !(plainHTML && text->mBlockquoting)) {
+ if (!plainHTML) prefaceResultStr += "<span class=\"moz-txt-citetags\">";
+
+ nsString citeTagsSource(StringHead(lineSourceStr, logicalLineStart));
+
+ // Convert to HTML
+ nsString citeTagsResultUnichar;
+ rv = conv->ScanTXT(citeTagsSource, 0 /* no recognition */,
+ citeTagsResultUnichar);
+ if (NS_FAILED(rv)) return -1;
+
+ prefaceResultStr.Append(NS_ConvertUTF16toUTF8(citeTagsResultUnichar));
+ if (!plainHTML) prefaceResultStr += "</span>";
+ }
+
+ // recognize signature
+ if ((lineSourceStr.Length() >= 4) && lineSourceStr.First() == '-' &&
+ Substring(lineSourceStr, 0, 3).EqualsLiteral("-- ") &&
+ (lineSourceStr[3] == '\r' || lineSourceStr[3] == '\n')) {
+ text->mIsSig = true;
+ if (!quoting) prefaceResultStr += "<div class=\"moz-txt-sig\">";
+ }
+
+ /* This is the main TXT to HTML conversion:
+ escaping (very important), eventually recognizing etc. */
+ nsString lineResultUnichar;
+
+ rv = conv->ScanTXT(Substring(lineSourceStr, logicalLineStart), whattodo,
+ lineResultUnichar);
+ NS_ENSURE_SUCCESS(rv, -1);
+
+ if (!(text->mIsSig && quoting && text->mStripSig)) {
+ status = MimeObject_write(obj, prefaceResultStr.get(),
+ prefaceResultStr.Length(), true);
+ if (status < 0) return status;
+ nsAutoCString outString;
+ if (obj->options->format_out != nsMimeOutput::nsMimeMessageSaveAs ||
+ !mailCharset || !*mailCharset)
+ CopyUTF16toUTF8(lineResultUnichar, outString);
+ else { // convert back to mailCharset before writing.
+ rv = nsMsgI18NConvertFromUnicode(nsDependentCString(mailCharset),
+ lineResultUnichar, outString);
+ NS_ENSURE_SUCCESS(rv, -1);
+ }
+
+ status = MimeObject_write(obj, outString.get(), outString.Length(), true);
+ } else {
+ status = 0;
+ }
+ } else {
+ status = MimeObject_write(obj, line, length, true);
+ }
+
+ return status;
+}