Bug 294356 - In a printed mail Thunderbird ignores the locale settings for the date generating month and day of week; Original patch by Tobias Koenig updated by Standard8 r=Standard8,bienvenu
authorTobias Koenig <tokoe@kde.org>
Thu, 23 Sep 2010 12:57:43 +0100
changeset 6404 75a2d4946290e21e71a3852fd33ac7bd0baa7420
parent 6403 eaedc1a132ec732c81804c0b8f83ef49eec2b360
child 6405 b07527a173c0188fd5bdd27d2160d1e574be3a7c
push idunknown
push userunknown
push dateunknown
reviewersStandard8, bienvenu
bugs294356
Bug 294356 - In a printed mail Thunderbird ignores the locale settings for the date generating month and day of week; Original patch by Tobias Koenig updated by Standard8 r=Standard8,bienvenu
mailnews/mime/emitters/src/nsMimeBaseEmitter.cpp
mailnews/mime/emitters/src/nsMimeBaseEmitter.h
mailnews/mime/emitters/src/nsMimeHtmlEmitter.cpp
mailnews/mime/emitters/src/nsMimeHtmlEmitter.h
--- a/mailnews/mime/emitters/src/nsMimeBaseEmitter.cpp
+++ b/mailnews/mime/emitters/src/nsMimeBaseEmitter.cpp
@@ -17,16 +17,17 @@
  * The Initial Developer of the Original Code is
  * Netscape Communications Corporation.
  * Portions created by the Initial Developer are Copyright (C) 1999
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Pierre Phaneuf <pp@ludusdesign.com>
  *   Henrik Gemal <mozilla@gemal.dk>
+ *   Tobias Koenig <tobias.koenig@credativ.de>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -55,19 +56,21 @@
 #include "nsIMimeStreamConverter.h"
 #include "nsIMimeConverter.h"
 #include "nsMsgMimeCID.h"
 #include "prlog.h"
 #include "prprf.h"
 #include "nsIMimeHeaders.h"
 #include "nsIMsgWindow.h"
 #include "nsIMsgMailNewsUrl.h"
+#include "nsDateTimeFormatCID.h"
 #include "nsServiceManagerUtils.h"
 #include "nsComponentManagerUtils.h"
 #include "nsMsgUtils.h"
+#include "nsTextFormatter.h"
 
 static PRLogModuleInfo * gMimeEmitterLogModule = nsnull;
 
 #define   MIME_HEADER_URL      "chrome://messenger/locale/mimeheader.properties"
 #define   MIME_URL             "chrome://messenger/locale/mime.properties"
 
 NS_IMPL_THREADSAFE_ADDREF(nsMimeBaseEmitter)
 NS_IMPL_THREADSAFE_RELEASE(nsMimeBaseEmitter)
@@ -691,47 +694,182 @@ nsMimeBaseEmitter::AddAllHeaders(const n
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // The following code is responsible for formatting headers in a manner that is
 // identical to the normal XUL output.
 ////////////////////////////////////////////////////////////////////////////////
 
 nsresult
+nsMimeBaseEmitter::GenerateDateString(const char * dateString, nsACString &formattedDate)
+{
+  nsresult rv = NS_OK;
+
+  if (!mDateFormatter) {
+    mDateFormatter = do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID, &rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  /**
+   * See if the user wants to have the date displayed in the senders
+   * timezone (including the timezone offset).
+   * We also evaluate the pref original_date which was introduced
+   * as makeshift in bug 118899.
+   */
+  PRBool displaySenderTimezone = PR_FALSE;
+  PRBool displayOriginalDate = PR_FALSE;
+
+  nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIPrefBranch> dateFormatPrefs;
+  rv = prefs->GetBranch("mailnews.display.", getter_AddRefs(dateFormatPrefs));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  dateFormatPrefs->GetBoolPref("date_senders_timezone", &displaySenderTimezone);
+  dateFormatPrefs->GetBoolPref("original_date", &displayOriginalDate);
+  // migrate old pref to date_senders_timezone
+  if (displayOriginalDate && !displaySenderTimezone)
+    dateFormatPrefs->SetBoolPref("date_senders_timezone", PR_TRUE);
+
+  PRExplodedTime explodedMsgTime;
+  rv = PR_ParseTimeStringToExplodedTime(dateString, PR_FALSE, &explodedMsgTime);
+  /**
+   * To determine the date format to use, comparison of current and message
+   * time has to be made. If displaying in local time, both timestamps have
+   * to be in local time. If displaying in senders time zone, leave the compare
+   * time in that time zone.
+   * Otherwise in TZ+0100 on 2009-03-12 a message from 2009-03-11T20:49-0700
+   * would be displayed as "20:49 -0700" though it in fact is not from the
+   * same day.
+   */
+  PRExplodedTime explodedCompTime;
+  if (displaySenderTimezone)
+    explodedCompTime = explodedMsgTime;
+  else
+    PR_ExplodeTime(PR_ImplodeTime(&explodedMsgTime), PR_LocalTimeParameters, &explodedCompTime);
+
+  PRExplodedTime explodedCurrentTime;
+  PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &explodedCurrentTime);
+
+  // if the message is from today, don't show the date, only the time. (i.e. 3:15 pm)
+  // if the message is from the last week, show the day of the week.   (i.e. Mon 3:15 pm)
+  // in all other cases, show the full date (03/19/01 3:15 pm)
+  nsDateFormatSelector dateFormat = kDateFormatShort;
+  if (explodedCurrentTime.tm_year == explodedCompTime.tm_year &&
+      explodedCurrentTime.tm_month == explodedCompTime.tm_month &&
+      explodedCurrentTime.tm_mday == explodedCompTime.tm_mday)
+  {
+    // same day...
+    dateFormat = kDateFormatNone;
+  }
+
+  nsAutoString formattedDateString;
+  if (NS_SUCCEEDED(rv))
+  {
+    rv = mDateFormatter->FormatPRExplodedTime(nsnull /* nsILocale* locale */,
+                                              dateFormat,
+                                              kTimeFormatNoSeconds,
+                                              &explodedCompTime,
+                                              formattedDateString);
+
+    if (NS_SUCCEEDED(rv))
+    {
+      if (displaySenderTimezone)
+      {
+        // offset of local time from UTC in minutes
+        PRInt32 senderoffset = (explodedMsgTime.tm_params.tp_gmt_offset +
+                                explodedMsgTime.tm_params.tp_dst_offset) / 60;
+        // append offset to date string
+        PRUnichar *tzstring =
+          nsTextFormatter::smprintf(NS_LITERAL_STRING(" %+05d").get(),
+                                    (senderoffset / 60 * 100) +
+                                    (senderoffset % 60));
+        formattedDateString.Append(tzstring);
+        nsTextFormatter::smprintf_free(tzstring);
+      }
+
+      CopyUTF16toUTF8(formattedDateString, formattedDate);
+    }
+  }
+
+  return rv;
+}
+
+char*
+nsMimeBaseEmitter::GetLocalizedDateString(const char * dateString)
+{
+  char *i18nValue = nsnull;
+
+  PRBool displayOriginalDate = PR_FALSE;
+  nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
+
+  if (prefBranch)
+    prefBranch->GetBoolPref("mailnews.display.original_date",
+                            &displayOriginalDate);
+
+  if (!displayOriginalDate)
+  {
+    nsCAutoString convertedDateString;
+    nsresult rv = GenerateDateString(dateString, convertedDateString);
+    if (NS_SUCCEEDED(rv))
+      i18nValue = strdup(convertedDateString.get());
+    else
+      i18nValue = strdup(dateString);
+  }
+  else
+    i18nValue = strdup(dateString);
+
+  return i18nValue;
+}
+
+nsresult
 nsMimeBaseEmitter::WriteHeaderFieldHTML(const char *field, const char *value)
 {
-  char  *newValue = nsnull;
+  char *newValue = nsnull;
+  char *i18nValue = nsnull;
 
   if ( (!field) || (!value) )
     return NS_OK;
 
   //
   // This is a check to see what the pref is for header display. If
   // We should only output stuff that corresponds with that setting.
   //
   if (!EmitThisHeaderForPrefSetting(mHeaderDisplayType, field))
     return NS_OK;
 
+  //
+  // If we encounter the 'Date' header we try to convert it's value
+  // into localized format.
+  //
+  if ( strcmp(field, "Date") == 0 )
+    i18nValue = GetLocalizedDateString(value);
+  else
+    i18nValue = strdup(value);
+
   if ( (mUnicodeConverter) && (mFormat != nsMimeOutput::nsMimeMessageSaveAs) )
   {
     nsCString tValue;
 
     // we're going to need a converter to convert
     nsresult rv = mUnicodeConverter->DecodeMimeHeaderToCharPtr(
-      value, nsnull, PR_FALSE, PR_TRUE, getter_Copies(tValue));
+      i18nValue, nsnull, PR_FALSE, PR_TRUE, getter_Copies(tValue));
     if (NS_SUCCEEDED(rv) && !tValue.IsEmpty())
       newValue = MsgEscapeHTML(tValue.get());
     else
-      newValue = MsgEscapeHTML(value);
+      newValue = MsgEscapeHTML(i18nValue);
   }
   else
   {
-    newValue = MsgEscapeHTML(value);
+    newValue = MsgEscapeHTML(i18nValue);
   }
 
+  free(i18nValue);
+
   if (!newValue)
     return NS_OK;
 
   mHTMLHeaders.Append("<tr>");
   mHTMLHeaders.Append("<td>");
 
   if (mFormat == nsMimeOutput::nsMimeMessageSaveAs)
     mHTMLHeaders.Append("<b>");
--- a/mailnews/mime/emitters/src/nsMimeBaseEmitter.h
+++ b/mailnews/mime/emitters/src/nsMimeBaseEmitter.h
@@ -51,16 +51,17 @@
 #include "nsIMsgHeaderParser.h"
 #include "nsIPipe.h"
 #include "nsIStringBundle.h"
 #include "nsCOMPtr.h"
 #include "nsVoidArray.h"
 #include "nsIMimeConverter.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
+#include "nsIDateTimeFormat.h"
 
 //
 // The base emitter will serve as the place to do all of the caching,
 // sorting, etc... of mail headers and bodies for this internally developed
 // emitter library. The other emitter classes in this file (nsMimeHTMLEmitter, etc.)
 // will only be concerned with doing output processing ONLY.
 //
 
@@ -166,11 +167,15 @@ protected:
   PRBool              mFirstHeaders;
 
   // For the format being used...
   PRInt32             mFormat;
 
   // For I18N Conversion...
   nsCOMPtr<nsIMimeConverter> mUnicodeConverter;
   nsString            mCharset;
+  nsCOMPtr<nsIDateTimeFormat> mDateFormatter;
+  nsresult GenerateDateString(const char * dateString, nsACString& formattedDate);
+  // The caller is expected to free the result of GetLocalizedDateString
+  char* GetLocalizedDateString(const char * dateString);
 };
 
 #endif /* _nsMimeBaseEmitter_h_ */
--- a/mailnews/mime/emitters/src/nsMimeHtmlEmitter.cpp
+++ b/mailnews/mime/emitters/src/nsMimeHtmlEmitter.cpp
@@ -53,22 +53,20 @@
 #include "prprf.h"
 #include "nsIStringEnumerator.h"
 #include "nsServiceManagerUtils.h"
 // hack: include this to fix opening news attachments.
 #include "nsINntpUrl.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIMimeConverter.h"
 #include "nsMsgMimeCID.h"
-#include "nsDateTimeFormatCID.h"
 #include "nsMsgUtils.h"
 #include "nsAutoPtr.h"
 #include "nsINetUtil.h"
 #include "nsMemory.h"
-#include "nsTextFormatter.h"
 
 #define VIEW_ALL_HEADERS 2
 
 /**
  * A helper class to implement nsIUTF8StringEnumerator
  */
 
 class nsMimeStringEnumerator : public nsIUTF8StringEnumerator {
@@ -310,125 +308,16 @@ NS_IMETHODIMP nsMimeHtmlDisplayEmitter::
     rv = pPrefBranch->GetIntPref("mail.show_headers", &viewMode);
 
     rv = BroadcastHeaders(headerSink, viewMode, bFromNewsgroups);
   } // if header Sink
 
   return NS_OK;
 }
 
-nsresult nsMimeHtmlDisplayEmitter::GenerateDateString(const char * dateString, nsACString &formattedDate)
-{
-  nsresult rv = NS_OK;
-
-  if (!mDateFormatter) {
-    mDateFormatter = do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID, &rv);
-    if (NS_FAILED(rv))
-      return rv;
-  }
-
-  /**
-   * See if the user wants to have the date displayed in the senders
-   * timezone (including the timezone offset).
-   * We also evaluate the pref original_date which was introduced
-   * as makeshift in bug 118899.
-   */
-  PRBool displaySenderTimezone = PR_FALSE;
-  PRBool displayOriginalDate = PR_FALSE;
-
-  nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIPrefBranch> dateFormatPrefs;
-  rv = prefs->GetBranch("mailnews.display.", getter_AddRefs(dateFormatPrefs));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  dateFormatPrefs->GetBoolPref("date_senders_timezone", &displaySenderTimezone);
-  dateFormatPrefs->GetBoolPref("original_date", &displayOriginalDate);
-  // migrate old pref to date_senders_timezone
-  if (displayOriginalDate && !displaySenderTimezone)
-    dateFormatPrefs->SetBoolPref("date_senders_timezone", PR_TRUE);
-
-  PRExplodedTime explodedMsgTime;
-  rv = PR_ParseTimeStringToExplodedTime(dateString, PR_FALSE, &explodedMsgTime);
-  /**
-   * To determine the date format to use, comparison of current and message
-   * time has to be made. If displaying in local time, both timestamps have
-   * to be in local time. If displaying in senders time zone, leave the compare
-   * time in that time zone.
-   * Otherwise in TZ+0100 on 2009-03-12 a message from 2009-03-11T20:49-0700
-   * would be displayed as "20:49 -0700" though it in fact is not from the
-   * same day.
-   */
-  PRExplodedTime explodedCompTime;
-  if (displaySenderTimezone)
-    explodedCompTime = explodedMsgTime;
-  else
-    PR_ExplodeTime(PR_ImplodeTime(&explodedMsgTime), PR_LocalTimeParameters, &explodedCompTime);
-
-  PRExplodedTime explodedCurrentTime;
-  PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &explodedCurrentTime);
-
-  // if the message is from today, don't show the date, only the time. (i.e. 3:15 pm)
-  // if the message is from the last week, show the day of the week.   (i.e. Mon 3:15 pm)
-  // in all other cases, show the full date (03/19/01 3:15 pm)
-  nsDateFormatSelector dateFormat = kDateFormatShort;
-  if (explodedCurrentTime.tm_year == explodedCompTime.tm_year &&
-      explodedCurrentTime.tm_month == explodedCompTime.tm_month &&
-      explodedCurrentTime.tm_mday == explodedCompTime.tm_mday)
-  {
-    // same day...
-    dateFormat = kDateFormatNone;
-  }
-  // the following chunk of code causes us to show a day instead of a number if the message was received
-  // within the last 7 days. i.e. Mon 5:10pm. We need to add a preference so folks to can enable this behavior
-  // if they want it.
-/*
-  else if (LL_CMP(currentTime, >, dateOfMsg))
-  {
-    PRInt64 microSecondsPerSecond, secondsInDays, microSecondsInDays;
-    LL_I2L(microSecondsPerSecond, PR_USEC_PER_SEC);
-    LL_UI2L(secondsInDays, 60 * 60 * 24 * 7); // how many seconds in 7 days.....
-    LL_MUL(microSecondsInDays, secondsInDays, microSecondsPerSecond); // turn that into microseconds
-
-    PRInt64 diff;
-    LL_SUB(diff, currentTime, dateOfMsg);
-    if (LL_CMP(diff, <=, microSecondsInDays)) // within the same week
-      dateFormat = kDateFormatWeekday;
-  }
-*/
-
-  nsAutoString formattedDateString;
-  if (NS_SUCCEEDED(rv))
-  {
-    rv = mDateFormatter->FormatPRExplodedTime(nsnull /* nsILocale* locale */,
-                                              dateFormat,
-                                              kTimeFormatNoSeconds,
-                                              &explodedCompTime,
-                                              formattedDateString);
-
-    if (NS_SUCCEEDED(rv))
-    {
-      if (displaySenderTimezone)
-      {
-        // offset of local time from UTC in minutes
-        PRInt32 senderoffset = (explodedMsgTime.tm_params.tp_gmt_offset + explodedMsgTime.tm_params.tp_dst_offset) / 60;
-        // append offset to date string
-        PRUnichar *tzstring = nsTextFormatter::smprintf(NS_LITERAL_STRING(" %+05d").get(), (senderoffset / 60 * 100) + (senderoffset % 60));
-        formattedDateString.Append(tzstring);
-        nsTextFormatter::smprintf_free(tzstring);
-      }
-
-      CopyUTF16toUTF8(formattedDateString, formattedDate);
-    }
-  }
-
-  return rv;
-}
-
 nsresult
 nsMimeHtmlDisplayEmitter::EndHeader(const nsACString &name)
 {
   if (mDocHeader && (mFormat != nsMimeOutput::nsMimeMessageFilterSniffer))
   {
     UtilityWriteCRLF("<html>");
     UtilityWriteCRLF("<head>");
 
--- a/mailnews/mime/emitters/src/nsMimeHtmlEmitter.h
+++ b/mailnews/mime/emitters/src/nsMimeHtmlEmitter.h
@@ -43,17 +43,16 @@
 #include "nsMimeRebuffer.h"
 #include "nsIStreamListener.h"
 #include "nsIOutputStream.h"
 #include "nsIInputStream.h"
 #include "nsIURI.h"
 #include "nsIChannel.h"
 #include "nsIMimeMiscStatus.h"
 #include "nsIMimeConverter.h"
-#include "nsIDateTimeFormat.h"
 
 class nsMimeHtmlDisplayEmitter : public nsMimeBaseEmitter {
 public:
     nsMimeHtmlDisplayEmitter ();
     nsresult Init();
 
     virtual       ~nsMimeHtmlDisplayEmitter (void);
 
@@ -83,15 +82,13 @@ protected:
 
     nsCOMPtr<nsIMsgHeaderSink> mHeaderSink;
 
     nsresult GetHeaderSink(nsIMsgHeaderSink ** aHeaderSink);
     PRBool BroadCastHeadersAndAttachments();
     nsresult StartAttachmentInBody(const nsACString &name,
                                    const char *contentType, const char *url);
 
-    nsCOMPtr<nsIDateTimeFormat> mDateFormatter;
-    nsresult GenerateDateString(const char * dateString, nsACString& formattedDate);
     nsresult BroadcastHeaders(nsIMsgHeaderSink * aHeaderSink, PRInt32 aHeaderMode, PRBool aFromNewsgroup);
 };
 
 
 #endif /* _nsMimeHtmlEmitter_h_ */