Bug 1530106 - Strip conditional CSS rules from HTML email. r=mkmelin
authorKai Engert <kaie@kuix.de>
Thu, 28 Nov 2019 16:58:42 +0100
changeset 28305 55d957f1d6befeb94b0806a45340d96d25fb4eef
parent 28304 92f8935e6e88062280ef1667f3b93dc2f6b6873a
child 28306 0211c8540f8473d9e538d27e39f4a922cbf033a3
push id16758
push userkaie@kuix.de
push dateTue, 03 Dec 2019 21:47:00 +0000
treeherdercomm-central@55d957f1d6be [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmkmelin
bugs1530106
Bug 1530106 - Strip conditional CSS rules from HTML email. r=mkmelin
mail/app/profile/all-thunderbird.js
mailnews/compose/src/nsMsgCompose.cpp
mailnews/mime/src/mimeTextHTMLParsed.cpp
--- a/mail/app/profile/all-thunderbird.js
+++ b/mail/app/profile/all-thunderbird.js
@@ -236,16 +236,19 @@ pref("mailnews.headers.show_n_lines_befo
 
 // We want to keep track of what items are appropriate in
 // XULStore.json. We use versioning to scrub out the things
 // that have become obsolete.
 // The value will always be set by startup code and must not be changed
 // here. A value of 0 means a new profile.
 pref("mail.ui-rdf.version", 0);
 
+// Strip CSS conditional rules in received and sent mail
+pref("mail.html_sanitize.drop_conditional_css", true);
+
 /////////////////////////////////////////////////////////////////
 // Overrides of the core mailnews.js and composer.js prefs
 /////////////////////////////////////////////////////////////////
 pref("mail.showCondensedAddresses", true); // show the friendly display name for people I know
 
 pref("mailnews.attachments.display.start_expanded", false);
 // hidden pref for changing how we present attachments in the message pane
 pref("mailnews.attachments.display.view", 0);
--- a/mailnews/compose/src/nsMsgCompose.cpp
+++ b/mailnews/compose/src/nsMsgCompose.cpp
@@ -72,16 +72,17 @@
 #include "mozilla/dom/HTMLImageElement.h"
 #include "mozilla/dom/Selection.h"
 #include "nsStreamConverter.h"
 #include "nsIObserverService.h"
 #include "nsIProtocolHandler.h"
 #include "nsContentUtils.h"
 #include "nsIFileURL.h"
 #include "nsTextNode.h"  // from dom/base
+#include "nsIParserUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::mailnews;
 
 static nsresult GetReplyHeaderInfo(int32_t *reply_header_type,
                                    nsString &reply_header_authorwrote,
                                    nsString &reply_header_ondateauthorwrote,
@@ -582,16 +583,23 @@ static void remove_plaintext_tag(nsStrin
     while ((index = body.Find("</plaintext", /* ignoreCase = */ true, index)) !=
            kNotFound) {
       body.Insert(u"x-", index + 2);
       index += 13;
     }
   }
 }
 
+static void remove_conditional_CSS(const nsAString &in, nsAString &out) {
+  nsCOMPtr<nsIParserUtils> parserUtils =
+      do_GetService(NS_PARSERUTILS_CONTRACTID);
+  parserUtils->Sanitize(in, nsIParserUtils::SanitizerRemoveOnlyConditionalCSS,
+                        out);
+}
+
 MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMP
 nsMsgCompose::ConvertAndLoadComposeWindow(nsString &aPrefix, nsString &aBuf,
                                           nsString &aSignature, bool aQuoted,
                                           bool aHTMLEditor) {
   NS_ASSERTION(m_editor, "ConvertAndLoadComposeWindow but no editor");
   NS_ENSURE_TRUE(m_editor && m_identity, NS_ERROR_NOT_INITIALIZED);
 
   // First, get the nsIEditor interface for future use
@@ -700,25 +708,33 @@ nsMsgCompose::ConvertAndLoadComposeWindo
               .EqualsLiteral(MIME_FORWARD_HTML_PREFIX)) {
         // We assign the opening tag inside "<HTML><BODY><BR><BR>" before the
         // two <br> elements.
         // This is a bit hacky but we know that the MIME code prepares the
         // forwarded content like this:
         // <HTML><BODY><BR><BR> + forwarded header + header table.
         // Note: We only do this when we prepare the message to be forwarded,
         // a re-opened saved draft of a forwarded message does not repeat this.
-        nsString newBody(aBuf);
         nsString divTag;
         divTag.AssignLiteral("<div class=\"moz-forward-container\">");
-        newBody.Insert(divTag, sizeof(MIME_FORWARD_HTML_PREFIX) - 1 - 8);
-        remove_plaintext_tag(newBody);
+        aBuf.Insert(divTag, sizeof(MIME_FORWARD_HTML_PREFIX) - 1 - 8);
+      }
+      remove_plaintext_tag(aBuf);
+
+      bool stripConditionalCSS = mozilla::Preferences::GetBool(
+          "mail.html_sanitize.drop_conditional_css", true);
+
+      if (stripConditionalCSS) {
+        nsString newBody;
+        remove_conditional_CSS(aBuf, newBody);
         htmlEditor->RebuildDocumentFromSource(newBody);
       } else {
         htmlEditor->RebuildDocumentFromSource(aBuf);
       }
+
       mInsertingQuotedContent = false;
 
       // When forwarding a message as inline, or editing as new (which could
       // contain unsanitized remote content), tag any embedded objects
       // with moz-do-not-send=true so they don't get attached upon send.
       if (isForwarded || mType == nsIMsgCompType::EditAsNew)
         (void)TagEmbeddedObjects(m_editor);
 
--- a/mailnews/mime/src/mimeTextHTMLParsed.cpp
+++ b/mailnews/mime/src/mimeTextHTMLParsed.cpp
@@ -21,16 +21,18 @@
 */
 
 #include "mimeTextHTMLParsed.h"
 #include "prmem.h"
 #include "prlog.h"
 #include "msgCore.h"
 #include "mozilla/dom/DOMParser.h"
 #include "mozilla/dom/Document.h"
+#include "mozilla/Preferences.h"
+#include "nsIParserUtils.h"
 #include "nsIDocumentEncoder.h"
 #include "mozilla/ErrorResult.h"
 #include "mimethtm.h"
 
 #define MIME_SUPERCLASS mimeInlineTextHTMLClass
 MimeDefClass(MimeInlineTextHTMLParsed, MimeInlineTextHTMLParsedClass,
              mimeInlineTextHTMLParsedClass, &MIME_SUPERCLASS);
 
@@ -91,18 +93,34 @@ static int MimeInlineTextHTMLParsed_pars
   NS_ENSURE_TRUE(encoder, -1);
   uint32_t aFlags = nsIDocumentEncoder::OutputRaw |
                     nsIDocumentEncoder::OutputDisallowLineBreaking;
   rv = encoder->Init(document, NS_LITERAL_STRING("text/html"), aFlags);
   NS_ENSURE_SUCCESS(rv, -1);
   rv = encoder->EncodeToString(parsed);
   NS_ENSURE_SUCCESS(rv, -1);
 
+  bool stripConditionalCSS = mozilla::Preferences::GetBool(
+      "mail.html_sanitize.drop_conditional_css", true);
+
+  nsCString resultCStr;
+  if (stripConditionalCSS) {
+    nsString cssCondStripped;
+    nsCOMPtr<nsIParserUtils> parserUtils =
+        do_GetService(NS_PARSERUTILS_CONTRACTID);
+    parserUtils->Sanitize(parsed,
+                          nsIParserUtils::SanitizerRemoveOnlyConditionalCSS,
+                          cssCondStripped);
+    parsed.Truncate();
+    resultCStr = NS_ConvertUTF16toUTF8(cssCondStripped);
+  } else {
+    resultCStr = NS_ConvertUTF16toUTF8(parsed);
+  }
+
   // Write it out.
-  NS_ConvertUTF16toUTF8 resultCStr(parsed);
   MimeInlineTextHTML_insert_lang_div(obj, resultCStr);
   MimeInlineTextHTML_remove_plaintext_tag(obj, resultCStr);
   status =
       ((MimeObjectClass *)&MIME_SUPERCLASS)
           ->parse_line(resultCStr.BeginWriting(), resultCStr.Length(), obj);
   rawHTML.Truncate();
   return status;
 }