Bug 1521007 - Support UTF-8 encoded MAPI data to avoid broken document names when sending documents from MS Word. r+a=jorgk
authorMike Kaganski <mikekaganski>
Wed, 20 Feb 2019 22:14:43 +0100
changeset 32089 b1baef69f9e63667c284a7ed59bd351fa16106ce
parent 32088 9a591621c69539ad40e272363b6e4eb4a49bb170
child 32090 eb1144931b6a67a8e7be00876737acf5140f9bf6
push id156
push usermozilla@jorgk.com
push dateThu, 21 Feb 2019 11:22:06 +0000
treeherdercomm-esr60@1a5b3ce230b6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1521007
Bug 1521007 - Support UTF-8 encoded MAPI data to avoid broken document names when sending documents from MS Word. r+a=jorgk * * * Bug 1521007 - Follow-up: fix variable name of UTF-8 indicator. r=me DONTBUILD * * * Bug 1521007 - Follow-up: also check for UTF-8 when copying file path. r=jorgk DONTBUILD * * * Bug 1521007 - Follow-up: Set SupportUTF8 registry key to indicate that Thunderbird is supporting UTF-8 at the MAPISendMail API. r=jorgk DONTBUILD
mail/installer/windows/nsis/shared.nsh
mailnews/mapi/mapihook/src/msgMapiHook.cpp
mailnews/mapi/mapihook/src/msgMapiHook.h
suite/installer/windows/nsis/shared.nsh
--- a/mail/installer/windows/nsis/shared.nsh
+++ b/mail/installer/windows/nsis/shared.nsh
@@ -353,16 +353,17 @@
   ${GetLongPath} "$INSTDIR\uninstall\helper.exe" $7
   ${GetLongPath} "$INSTDIR\mozMapi32_InUse.dll" $6
 
   StrCpy $0 "Software\Clients\Mail\${ClientsRegName}"
 
   WriteRegStr ${RegKey} "$0" "" "${ClientsRegName}"
   WriteRegStr ${RegKey} "$0\DefaultIcon" "" "$8,0"
   WriteRegStr ${RegKey} "$0" "DLLPath" "$6"
+  WriteRegDWORD ${RegKey} "$0" "SupportUTF8" 1
 
   ; The MapiProxy dll can exist in multiple installs of the application.
   ; Registration occurs as follows with the last action to occur being the one
   ; that wins:
   ; On install and software update when helper.exe runs with the /PostUpdate
   ; argument. On setting the application as the system's default application
   ; using Window's "Set program access and defaults".
 
--- a/mailnews/mapi/mapihook/src/msgMapiHook.cpp
+++ b/mailnews/mapi/mapihook/src/msgMapiHook.cpp
@@ -345,17 +345,17 @@ nsresult nsMapiHook::BlindSendMail (unsi
     PR_CExitMonitor(pSendListener);
     NS_ProcessPendingEvents(thread);
   }
 
   return rv ;
 }
 
 nsresult nsMapiHook::HandleAttachments (nsIMsgCompFields * aCompFields, int32_t aFileCount,
-                                        lpnsMapiFileDesc aFiles)
+                                        lpnsMapiFileDesc aFiles, bool aIsUTF8)
 {
     nsresult rv = NS_OK ;
     // Do nothing if there are no files to process.
     if (!aFiles || aFileCount <= 0)
         return NS_OK;
 
     nsAutoCString Attachments ;
     nsAutoCString TempFiles ;
@@ -365,21 +365,27 @@ nsresult nsMapiHook::HandleAttachments (
     nsCOMPtr <nsIFile> pTempDir = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv) ;
     if (NS_FAILED(rv) || (!pTempDir) ) return rv ;
 
     for (int i=0 ; i < aFileCount ; i++)
     {
         if (aFiles[i].lpszPathName)
         {
             // check if attachment exists
-            pFile->InitWithNativePath(nsDependentCString((const char*)aFiles[i].lpszPathName));
+            if (!aIsUTF8)
+              pFile->InitWithNativePath(nsDependentCString(aFiles[i].lpszPathName));
+            else
+              pFile->InitWithPath(NS_ConvertUTF8toUTF16(aFiles[i].lpszPathName));
 
             bool bExist ;
             rv = pFile->Exists(&bExist) ;
-            MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("nsMapiHook::HandleAttachments: filename: %s path: %s exists = %s \n", (const char*)aFiles[i].lpszFileName, (const char*)aFiles[i].lpszPathName, bExist ? "true" : "false"));
+            MOZ_LOG(MAPI, mozilla::LogLevel::Debug,
+              ("nsMapiHook::HandleAttachments: filename: %s path: %s exists = %s\n",
+               (const char*)aFiles[i].lpszFileName,
+               (const char*)aFiles[i].lpszPathName, bExist ? "true" : "false"));
             if (NS_FAILED(rv) || (!bExist) ) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST ;
 
             //Temp Directory
             nsCOMPtr <nsIFile> pTempDir;
             NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(pTempDir));
 
             // create a new sub directory called moz_mapi underneath the temp directory
             pTempDir->AppendRelativePath(NS_LITERAL_STRING("moz_mapi"));
@@ -394,18 +400,21 @@ nsresult nsMapiHook::HandleAttachments (
 
             nsAutoString leafName ;
             // convert to Unicode using Platform charset
             // leafName already contains a unicode leafName from lpszPathName. If we were given
             // a value for lpszFileName, use it. Otherwise stick with leafName
             if (aFiles[i].lpszFileName)
             {
                 nsAutoString wholeFileName;
-                NS_CopyNativeToUnicode(nsDependentCString((char *)aFiles[i].lpszFileName),
-                                       wholeFileName);
+                if (!aIsUTF8)
+                    NS_CopyNativeToUnicode(nsDependentCString(aFiles[i].lpszFileName),
+                                           wholeFileName);
+                else
+                    wholeFileName.Append(NS_ConvertUTF8toUTF16(aFiles[i].lpszFileName));
                 // need to find the last '\' and find the leafname from that.
                 int32_t lastSlash = wholeFileName.RFindChar(char16_t('\\'));
                 if (lastSlash != kNotFound)
                   leafName.Assign(Substring(wholeFileName, lastSlash + 1));
                 else
                   leafName.Assign(wholeFileName);
             }
             else
@@ -458,21 +467,25 @@ nsresult nsMapiHook::HandleAttachments (
 }
 
 
 // this is used to convert non Unicode data and then populate comp fields
 nsresult nsMapiHook::PopulateCompFieldsWithConversion(lpnsMapiMessage aMessage,
                                     nsIMsgCompFields * aCompFields)
 {
   nsresult rv = NS_OK;
+  bool isUTF8 = aMessage->ulReserved == CP_UTF8;
 
   if (aMessage->lpOriginator)
   {
     nsAutoString From;
-    From.Append(NS_ConvertASCIItoUTF16((char *) aMessage->lpOriginator->lpszAddress));
+    if (!isUTF8)
+        From.Append(NS_ConvertASCIItoUTF16(aMessage->lpOriginator->lpszAddress));
+    else
+        From.Append(NS_ConvertUTF8toUTF16(aMessage->lpOriginator->lpszAddress));
     aCompFields->SetFrom (From);
   }
 
   nsAutoString To;
   nsAutoString Cc;
   nsAutoString Bcc;
   NS_NAMED_LITERAL_STRING(Comma, ",");
   if (aMessage->lpRecips)
@@ -486,29 +499,38 @@ nsresult nsMapiHook::PopulateCompFieldsW
         if (!PL_strncasecmp(addressWithoutType, "SMTP:", 5))
           addressWithoutType += 5;
 
         switch (aMessage->lpRecips[i].ulRecipClass)
         {
         case MAPI_TO :
           if (!To.IsEmpty())
             To += Comma ;
-          To.Append(NS_ConvertASCIItoUTF16(addressWithoutType));
+          if (!isUTF8)
+              To.Append(NS_ConvertASCIItoUTF16(addressWithoutType));
+          else
+              To.Append(NS_ConvertUTF8toUTF16(addressWithoutType));
           break ;
 
         case MAPI_CC :
           if (!Cc.IsEmpty())
             Cc += Comma ;
-          Cc.Append(NS_ConvertASCIItoUTF16(addressWithoutType));
+          if (!isUTF8)
+              Cc.Append(NS_ConvertASCIItoUTF16(addressWithoutType));
+          else
+              Cc.Append(NS_ConvertUTF8toUTF16(addressWithoutType));
           break ;
 
         case MAPI_BCC :
           if (!Bcc.IsEmpty())
               Bcc += Comma ;
-          Bcc.Append(NS_ConvertASCIItoUTF16(addressWithoutType));
+          if (!isUTF8)
+              Bcc.Append(NS_ConvertASCIItoUTF16(addressWithoutType));
+          else
+              Bcc.Append(NS_ConvertUTF8toUTF16(addressWithoutType));
           break ;
         }
       }
     }
   }
 
   // set To, Cc, Bcc
   aCompFields->SetTo (To) ;
@@ -516,32 +538,38 @@ nsresult nsMapiHook::PopulateCompFieldsW
   aCompFields->SetBcc (Bcc) ;
 
   MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("to: %s cc: %s bcc: %s \n", NS_ConvertUTF16toUTF8(To).get(), NS_ConvertUTF16toUTF8(Cc).get(), NS_ConvertUTF16toUTF8(Bcc).get()));
 
   // set subject
   if (aMessage->lpszSubject)
   {
     nsAutoString Subject ;
-    rv = NS_CopyNativeToUnicode(nsDependentCString((char *) aMessage->lpszSubject),
-                                Subject);
+    if (!isUTF8)
+        rv = NS_CopyNativeToUnicode(nsDependentCString(aMessage->lpszSubject),
+                                    Subject);
+    else
+        Subject.Append(NS_ConvertUTF8toUTF16(aMessage->lpszSubject));
     if (NS_FAILED(rv)) return rv;
     aCompFields->SetSubject(Subject);
   }
 
   // handle attachments as File URL
-  rv = HandleAttachments(aCompFields, aMessage->nFileCount, aMessage->lpFiles);
+  rv = HandleAttachments(aCompFields, aMessage->nFileCount, aMessage->lpFiles, isUTF8);
   if (NS_FAILED(rv)) return rv ;
 
   // set body
   if (aMessage->lpszNoteText)
   {
     nsAutoString Body ;
-    rv = NS_CopyNativeToUnicode(nsDependentCString((char *) aMessage->lpszNoteText),
-                                Body);
+    if (!isUTF8)
+        rv = NS_CopyNativeToUnicode(nsDependentCString(aMessage->lpszNoteText),
+                                    Body);
+    else
+        Body.Append(NS_ConvertUTF8toUTF16(aMessage->lpszNoteText));
     if (NS_FAILED(rv)) return rv ;
     if (Body.IsEmpty() || Body.Last() != '\n')
       Body.AppendLiteral(CRLF);
 
     // This is needed when Simple MAPI is used without a compose window.
     // See bug 1366196.
     if (Body.Find("<html>") == kNotFound)
       aCompFields->SetForcePlainText(true);
--- a/mailnews/mapi/mapihook/src/msgMapiHook.h
+++ b/mailnews/mapi/mapihook/src/msgMapiHook.h
@@ -17,16 +17,16 @@ class nsMapiHook
 
         static bool IsBlindSendAllowed () ;
         static nsresult BlindSendMail (unsigned long aSession, nsIMsgCompFields * aCompFields) ;
         static nsresult ShowComposerWindow (unsigned long aSession, nsIMsgCompFields * aCompFields) ;
         static nsresult PopulateCompFieldsWithConversion(lpnsMapiMessage aMessage,
                                         nsIMsgCompFields * aCompFields) ;
         static nsresult PopulateCompFieldsForSendDocs(nsIMsgCompFields * aCompFields,
                                         ULONG aFlags, LPTSTR aDelimChar, LPTSTR aFilePaths) ;
-        static nsresult HandleAttachments (nsIMsgCompFields * aCompFields, int32_t aFileCount,
-                                           lpnsMapiFileDesc aFiles) ;
+        static nsresult HandleAttachments(nsIMsgCompFields *aCompFields, int32_t aFileCount,
+                                          lpnsMapiFileDesc aFiles, bool aIsUTF8);
         static void CleanUp();
 
         static bool isMapiService;
 };
 
 #endif  // MSG_MAPI_HOOK_H_
--- a/suite/installer/windows/nsis/shared.nsh
+++ b/suite/installer/windows/nsis/shared.nsh
@@ -462,16 +462,17 @@
   ${GetLongPath} "$INSTDIR\${FileMainEXE}" $8
   ${GetLongPath} "$INSTDIR\uninstall\helper.exe" $7
   ${GetLongPath} "$INSTDIR\mozMapi32_InUse.dll" $6
 
   StrCpy $0 "Software\Clients\Mail\${BrandFullNameInternal}"
   WriteRegStr HKLM "$0" "" "${BrandFullNameInternal}"
   WriteRegStr HKLM "$0\DefaultIcon" "" "$8,0"
   WriteRegStr HKLM "$0" "DLLPath" "$6"
+  WriteRegDWORD HKLM "$0" "SupportUTF8" 1
 
   ; The MapiProxy dll can be used by multiple applications but
   ; is only registered for the last application installed. When the last
   ; application installed is uninstalled MapiProxy.dll will no longer be
   ; registered.
   !ifndef NO_LOG
     ${LogHeader} "DLL Registration"
   !endif