summaryrefslogtreecommitdiff
path: root/mailnews
diff options
context:
space:
mode:
authorBrian Smith <brian@dbsoft.org>2022-04-26 10:13:11 -0500
committerBrian Smith <brian@dbsoft.org>2022-04-26 10:19:04 -0500
commit3daf711085889bad1bd68651bc4e8790412ae105 (patch)
treef5b0e4c1befb320cdf158e1839ac5e273373087f /mailnews
parent7fe702603066e7f122d5dd66a3a1892ac7e06215 (diff)
downloaduxp-3daf711085889bad1bd68651bc4e8790412ae105.tar.gz
Issue #1829 - Revert “Issue #1751 -- Remove XP_MACOSX conditionals from the rest of the tree.”
This also removes some PP abuse and takes file entries out of PP when no longer needed without XP_MACOSX conditionals. This reverts commit 6f707bde95dab6998ac204f9ee6c925ee230c740.
Diffstat (limited to 'mailnews')
-rw-r--r--mailnews/addrbook/public/nsAbBaseCID.h41
-rw-r--r--mailnews/base/prefs/content/AccountWizard.xul4
-rw-r--r--mailnews/base/search/src/nsMsgFilter.cpp5
-rw-r--r--mailnews/base/src/nsMessenger.cpp6
-rw-r--r--mailnews/base/src/nsMsgMailSession.cpp8
-rw-r--r--mailnews/base/src/nsStatusBarBiffManager.cpp2
-rw-r--r--mailnews/base/util/nsMsgUtils.cpp4
-rw-r--r--mailnews/build/nsMailModule.cpp46
-rw-r--r--mailnews/compose/src/nsMsgAttachmentHandler.cpp351
-rw-r--r--mailnews/compose/src/nsMsgAttachmentHandler.h50
-rw-r--r--mailnews/compose/src/nsMsgSend.cpp4
-rw-r--r--mailnews/imap/src/nsIMAPBodyShell.cpp21
-rw-r--r--mailnews/import/applemail/src/moz.build14
-rw-r--r--mailnews/import/applemail/src/nsAppleMailImport.cpp623
-rw-r--r--mailnews/import/applemail/src/nsAppleMailImport.h78
-rw-r--r--mailnews/import/applemail/src/nsEmlxHelperUtils.h55
-rw-r--r--mailnews/import/applemail/src/nsEmlxHelperUtils.mm240
-rw-r--r--mailnews/import/build/nsImportModule.cpp31
-rw-r--r--mailnews/import/content/importDialog.xul4
-rw-r--r--mailnews/jar.mn2
-rw-r--r--mailnews/mailnews.js22
-rw-r--r--mailnews/mime/src/mimeebod.cpp14
-rw-r--r--mailnews/mime/src/mimemapl.cpp24
-rw-r--r--mailnews/mime/src/mimemult.cpp17
-rw-r--r--mailnews/moz.build5
25 files changed, 1662 insertions, 9 deletions
diff --git a/mailnews/addrbook/public/nsAbBaseCID.h b/mailnews/addrbook/public/nsAbBaseCID.h
index 611300d0ab..0dcc630c50 100644
--- a/mailnews/addrbook/public/nsAbBaseCID.h
+++ b/mailnews/addrbook/public/nsAbBaseCID.h
@@ -387,6 +387,47 @@
#define NS_ABVIEW_CONTRACTID \
"@mozilla.org/addressbook/abview;1"
+#ifdef XP_MACOSX
+//
+// nsAbOSXDirectory
+//
+#define NS_ABOSXDIRECTORY_PREFIX "moz-abosxdirectory"
+#define NS_ABOSXCARD_PREFIX "moz-abosxcard"
+
+#define NS_ABOSXDIRECTORY_CONTRACTID \
+ NS_AB_DIRECTORY_TYPE_CONTRACTID_PREFIX NS_ABOSXDIRECTORY_PREFIX
+
+#define NS_ABOSXDIRECTORY_CID \
+{ /* {83781cc6-c682-11d6-bdeb-0005024967b8}*/ \
+ 0x83781cc6, 0xc682, 0x11d6, \
+ {0xbd, 0xeb, 0x00, 0x05, 0x02, 0x49, 0x67, 0xb8} \
+}
+
+//
+// nsAbOSXCard
+//
+#define NS_ABOSXCARD_CONTRACTID \
+ NS_AB_DIRECTORY_TYPE_CONTRACTID_PREFIX NS_ABOSXCARD_PREFIX
+
+#define NS_ABOSXCARD_CID \
+{ /* {89bbf582-c682-11d6-bc9d-0005024967b8}*/ \
+ 0x89bbf582, 0xc682, 0x11d6, \
+ {0xbc, 0x9d, 0x00, 0x05, 0x02, 0x49, 0x67, 0xb8} \
+}
+
+//
+// OS X directory factory
+//
+#define NS_ABOSXDIRFACTORY_CONTRACTID \
+ NS_AB_DIRECTORY_FACTORY_CONTRACTID_PREFIX NS_ABOSXDIRECTORY_PREFIX
+
+#define NS_ABOSXDIRFACTORY_CID \
+{ /* {90efe2fe-c682-11d6-9c83-0005024967b8}*/ \
+ 0x90efe2fe, 0xc682, 0x11d6, \
+ {0x9c, 0x83, 0x00, 0x05, 0x02, 0x49, 0x67, 0xb8} \
+}
+#endif
+
#define NS_MSGVCARDSERVICE_CID \
{ 0x3c4ac0da, 0x2cda, 0x4018, \
{ 0x95, 0x51, 0xe1, 0x58, 0xb2, 0xe1, 0x22, 0xd3 }}
diff --git a/mailnews/base/prefs/content/AccountWizard.xul b/mailnews/base/prefs/content/AccountWizard.xul
index 9d825084b2..2aee2e3a5d 100644
--- a/mailnews/base/prefs/content/AccountWizard.xul
+++ b/mailnews/base/prefs/content/AccountWizard.xul
@@ -343,7 +343,11 @@
checked="true"/>
</hbox>
<spacer flex="1"/>
+#ifndef XP_MACOSX
<description>&clickFinish.label;</description>
+#else
+ <description>&clickFinish.labelMac;</description>
+#endif
</vbox>
</wizardpage>
diff --git a/mailnews/base/search/src/nsMsgFilter.cpp b/mailnews/base/search/src/nsMsgFilter.cpp
index d7e9ac9408..e94240f299 100644
--- a/mailnews/base/search/src/nsMsgFilter.cpp
+++ b/mailnews/base/search/src/nsMsgFilter.cpp
@@ -822,6 +822,11 @@ nsresult nsMsgFilter::ConvertMoveOrCopyToFolderValue(nsIMsgRuleAction *filterAct
if (offset != -1)
moveValue.Cut(offset, 4);
+#ifdef XP_MACOSX
+ nsCString unescapedMoveValue;
+ MsgUnescapeString(moveValue, 0, unescapedMoveValue);
+ moveValue = unescapedMoveValue;
+#endif
destFolderUri.Append('/');
if (filterVersion == k45Version)
{
diff --git a/mailnews/base/src/nsMessenger.cpp b/mailnews/base/src/nsMessenger.cpp
index 8719530f79..953b462b6a 100644
--- a/mailnews/base/src/nsMessenger.cpp
+++ b/mailnews/base/src/nsMessenger.cpp
@@ -698,6 +698,7 @@ nsresult nsMessenger::SaveAttachment(nsIFile *aFile,
saveListener->QueryInterface(NS_GET_IID(nsIStreamListener),
getter_AddRefs(convertedListener));
+#ifndef XP_MACOSX
// if the content type is bin hex we are going to do a hokey hack and make sure we decode the bin hex
// when saving an attachment to disk..
if (MsgLowerCaseEqualsLiteral(aContentType, APPLICATION_BINHEX))
@@ -712,6 +713,7 @@ nsresult nsMessenger::SaveAttachment(nsIFile *aFile,
channelSupport,
getter_AddRefs(convertedListener));
}
+#endif
nsCOMPtr<nsIURI> dummyNull;
if (fetchService)
rv = fetchService->FetchMimePart(URL, fullMessageUri.get(),
@@ -769,6 +771,10 @@ nsMessenger::SaveAttachmentToFolder(const nsACString& contentType, const nsACStr
ConvertAndSanitizeFileName(PromiseFlatCString(displayName).get(), unescapedFileName);
rv = attachmentDestination->Append(unescapedFileName);
NS_ENSURE_SUCCESS(rv, rv);
+#ifdef XP_MACOSX
+ rv = attachmentDestination->CreateUnique(nsIFile::NORMAL_FILE_TYPE, ATTACHMENT_PERMISSION);
+ NS_ENSURE_SUCCESS(rv, rv);
+#endif
rv = SaveAttachment(attachmentDestination, url, messageUri, contentType, nullptr, nullptr);
attachmentDestination.swap(*aOutFile);
diff --git a/mailnews/base/src/nsMsgMailSession.cpp b/mailnews/base/src/nsMsgMailSession.cpp
index 20d6f045c3..f9e396988c 100644
--- a/mailnews/base/src/nsMsgMailSession.cpp
+++ b/mailnews/base/src/nsMsgMailSession.cpp
@@ -353,9 +353,11 @@ NS_IMETHODIMP nsMsgMailSession::AddMsgWindow(nsIMsgWindow *msgWindow)
NS_IMETHODIMP nsMsgMailSession::RemoveMsgWindow(nsIMsgWindow *msgWindow)
{
mWindows.RemoveObject(msgWindow);
- // For suite, we don't want to disable mailnews when the last mail window
- // is closed (other component windows may still be open).
-#if !defined(MOZ_SUITE)
+ // Mac keeps a hidden window open so the app doesn't shut down when
+ // the last window is closed. So don't shutdown the account manager in that
+ // case. Similarly, for suite, we don't want to disable mailnews when the
+ // last mail window is closed.
+#if !defined(XP_MACOSX) && !defined(MOZ_SUITE)
if (!mWindows.Count())
{
nsresult rv;
diff --git a/mailnews/base/src/nsStatusBarBiffManager.cpp b/mailnews/base/src/nsStatusBarBiffManager.cpp
index 08dfb7b76e..27f393986d 100644
--- a/mailnews/base/src/nsStatusBarBiffManager.cpp
+++ b/mailnews/base/src/nsStatusBarBiffManager.cpp
@@ -136,11 +136,13 @@ nsresult nsStatusBarBiffManager::PlayBiffSound(const char *aPrefBranch)
}
}
}
+#ifndef XP_MACOSX
// if nothing played, play the default system sound
if (!customSoundPlayed) {
rv = mSound->PlayEventSound(nsISound::EVENT_NEW_MAIL_RECEIVED);
NS_ENSURE_SUCCESS(rv, rv);
}
+#endif
return rv;
}
diff --git a/mailnews/base/util/nsMsgUtils.cpp b/mailnews/base/util/nsMsgUtils.cpp
index 6fc884d510..44609bea00 100644
--- a/mailnews/base/util/nsMsgUtils.cpp
+++ b/mailnews/base/util/nsMsgUtils.cpp
@@ -611,7 +611,7 @@ nsresult NS_MsgCreatePathStringFromFolderURI(const char *aFolderURI,
? oldPath.FindChar('/', startSlashPos + 1) - 1 : oldPath.Length() - 1;
if (endSlashPos < 0)
endSlashPos = oldPath.Length();
-#if defined(XP_UNIX)
+#if defined(XP_UNIX) || defined(XP_MACOSX)
bool isLocalUri = aScheme.EqualsLiteral("none") ||
aScheme.EqualsLiteral("pop3") ||
aScheme.EqualsLiteral("rss");
@@ -636,7 +636,7 @@ nsresult NS_MsgCreatePathStringFromFolderURI(const char *aFolderURI,
CopyUTF16toMUTF7(pathPiece, tmp);
CopyASCIItoUTF16(tmp, pathPiece);
}
-#if defined(XP_UNIX)
+#if defined(XP_UNIX) || defined(XP_MACOSX)
// Don't hash path pieces because local mail folder uri's have already
// been hashed. We're only doing this on the mac to limit potential
// regressions.
diff --git a/mailnews/build/nsMailModule.cpp b/mailnews/build/nsMailModule.cpp
index dea26047a0..5b86b4c3ef 100644
--- a/mailnews/build/nsMailModule.cpp
+++ b/mailnews/build/nsMailModule.cpp
@@ -102,6 +102,9 @@
#ifdef XP_WIN
#include "nsMessengerWinIntegration.h"
#endif
+#ifdef XP_MACOSX
+#include "nsMessengerOSXIntegration.h"
+#endif
#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2)
#include "nsMessengerUnixIntegration.h"
#endif
@@ -154,6 +157,12 @@
#include "nsAbOutlookDirectory.h"
#endif
+#ifdef XP_MACOSX
+#include "nsAbOSXDirectory.h"
+#include "nsAbOSXCard.h"
+#include "nsAbOSXDirFactory.h"
+#endif
+
////////////////////////////////////////////////////////////////////////////////
// bayesian spam filter includes
////////////////////////////////////////////////////////////////////////////////
@@ -370,6 +379,9 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgShutdownService)
#ifdef XP_WIN
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMessengerWinIntegration, Init)
#endif
+#ifdef XP_MACOSX
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMessengerOSXIntegration, Init)
+#endif
#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMessengerUnixIntegration, Init)
#endif
@@ -427,6 +439,9 @@ NS_DEFINE_NAMED_CID(NS_MSGNOTIFICATIONSERVICE_CID);
#ifdef XP_WIN
NS_DEFINE_NAMED_CID(NS_MESSENGERWININTEGRATION_CID);
#endif
+#ifdef XP_MACOSX
+NS_DEFINE_NAMED_CID(NS_MESSENGEROSXINTEGRATION_CID);
+#endif
#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2)
NS_DEFINE_NAMED_CID(NS_MESSENGERUNIXINTEGRATION_CID);
#endif
@@ -484,6 +499,12 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsAbView)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgVCardService)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAbLDIFService)
+#ifdef XP_MACOSX
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsAbOSXDirectory)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsAbOSXCard)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsAbOSXDirFactory)
+#endif
+
NS_DEFINE_NAMED_CID(NS_ABMANAGER_CID);
NS_DEFINE_NAMED_CID(NS_ABDIRECTORY_CID);
NS_DEFINE_NAMED_CID(NS_ABMDBDIRECTORY_CID);
@@ -515,6 +536,11 @@ NS_DEFINE_NAMED_CID(NS_ABLDAP_REPLICATIONQUERY_CID);
NS_DEFINE_NAMED_CID(NS_ABLDAP_PROCESSREPLICATIONDATA_CID);
#endif
NS_DEFINE_NAMED_CID(NS_ABDIRECTORYQUERYPROXY_CID);
+#ifdef XP_MACOSX
+NS_DEFINE_NAMED_CID(NS_ABOSXDIRECTORY_CID);
+NS_DEFINE_NAMED_CID(NS_ABOSXCARD_CID);
+NS_DEFINE_NAMED_CID(NS_ABOSXDIRFACTORY_CID);
+#endif
NS_DEFINE_NAMED_CID(NS_ABVIEW_CID);
NS_DEFINE_NAMED_CID(NS_MSGVCARDSERVICE_CID);
NS_DEFINE_NAMED_CID(NS_ABLDIFSERVICE_CID);
@@ -897,6 +923,9 @@ const mozilla::Module::CIDEntry kMailNewsCIDs[] = {
#ifdef XP_WIN
{ &kNS_MESSENGERWININTEGRATION_CID, false, NULL, nsMessengerWinIntegrationConstructor},
#endif
+#ifdef XP_MACOSX
+ { &kNS_MESSENGEROSXINTEGRATION_CID, false, NULL, nsMessengerOSXIntegrationConstructor},
+#endif
#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2)
{ &kNS_MESSENGERUNIXINTEGRATION_CID, false, NULL, nsMessengerUnixIntegrationConstructor},
#endif
@@ -939,6 +968,11 @@ const mozilla::Module::CIDEntry kMailNewsCIDs[] = {
{ &kNS_ABLDAPDIRFACTORY_CID, false, NULL, nsAbLDAPDirFactoryConstructor },
#endif
{ &kNS_ABDIRECTORYQUERYPROXY_CID, false, NULL, nsAbDirectoryQueryProxyConstructor },
+#ifdef XP_MACOSX
+ { &kNS_ABOSXDIRECTORY_CID, false, NULL, nsAbOSXDirectoryConstructor },
+ { &kNS_ABOSXCARD_CID, false, NULL, nsAbOSXCardConstructor },
+ { &kNS_ABOSXDIRFACTORY_CID, false, NULL, nsAbOSXDirFactoryConstructor },
+#endif
{ &kNS_ABVIEW_CID, false, NULL, nsAbViewConstructor },
{ &kNS_MSGVCARDSERVICE_CID, false, NULL, nsMsgVCardServiceConstructor },
{ &kNS_ABLDIFSERVICE_CID, false, NULL, nsAbLDIFServiceConstructor },
@@ -1107,6 +1141,9 @@ const mozilla::Module::ContractIDEntry kMailNewsContracts[] = {
#ifdef XP_WIN
{ NS_MESSENGEROSINTEGRATION_CONTRACTID, &kNS_MESSENGERWININTEGRATION_CID },
#endif
+#ifdef XP_MACOSX
+ { NS_MESSENGEROSINTEGRATION_CONTRACTID, &kNS_MESSENGEROSXINTEGRATION_CID },
+#endif
#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2)
{ NS_MESSENGEROSINTEGRATION_CONTRACTID, &kNS_MESSENGERUNIXINTEGRATION_CID },
#endif
@@ -1153,6 +1190,11 @@ const mozilla::Module::ContractIDEntry kMailNewsContracts[] = {
#endif
{ NS_ABDIRECTORYQUERYPROXY_CONTRACTID, &kNS_ABDIRECTORYQUERYPROXY_CID },
+#ifdef XP_MACOSX
+ { NS_ABOSXDIRECTORY_CONTRACTID, &kNS_ABOSXDIRECTORY_CID },
+ { NS_ABOSXCARD_CONTRACTID, &kNS_ABOSXCARD_CID },
+ { NS_ABOSXDIRFACTORY_CONTRACTID, &kNS_ABOSXDIRFACTORY_CID },
+#endif
{ NS_ABVIEW_CONTRACTID, &kNS_ABVIEW_CID },
{ NS_MSGVCARDSERVICE_CONTRACTID, &kNS_MSGVCARDSERVICE_CID },
{ NS_ABLDIFSERVICE_CONTRACTID, &kNS_ABLDIFSERVICE_CID },
@@ -1301,6 +1343,10 @@ static const mozilla::Module::CategoryEntry kMailNewsCategories[] = {
{ XPCOM_DIRECTORY_PROVIDER_CATEGORY, "mail-directory-provider", NS_MAILDIRPROVIDER_CONTRACTID },
{ "content-policy", NS_MSGCONTENTPOLICY_CONTRACTID, NS_MSGCONTENTPOLICY_CONTRACTID },
MAILNEWSDLF_CATEGORIES
+#ifdef XP_MACOSX
+ { "app-startup", NS_MESSENGEROSINTEGRATION_CONTRACTID, "service," NS_MESSENGEROSINTEGRATION_CONTRACTID}
+,
+#endif
// Address Book Entries
{ "command-line-handler", "m-addressbook", NS_ABMANAGERSTARTUPHANDLER_CONTRACTID },
// Bayesian Filter Entries
diff --git a/mailnews/compose/src/nsMsgAttachmentHandler.cpp b/mailnews/compose/src/nsMsgAttachmentHandler.cpp
index 3c7e08bc13..4994c3fe69 100644
--- a/mailnews/compose/src/nsMsgAttachmentHandler.cpp
+++ b/mailnews/compose/src/nsMsgAttachmentHandler.cpp
@@ -36,6 +36,77 @@
#include "mozilla/mailnews/MimeEncoder.h"
#include "nsIPrincipal.h"
+///////////////////////////////////////////////////////////////////////////
+// Mac Specific Attachment Handling for AppleDouble Encoded Files
+///////////////////////////////////////////////////////////////////////////
+#ifdef XP_MACOSX
+
+#define AD_WORKING_BUFF_SIZE FILE_IO_BUFFER_SIZE
+
+extern void MacGetFileType(nsIFile *fs, bool *useDefault, char **type, char **encoding);
+
+#include "nsILocalFileMac.h"
+
+/* static */
+nsresult nsSimpleZipper::Zip(nsIFile *aInputFile, nsIFile *aOutputFile)
+{
+ // create zipwriter object
+ nsresult rv;
+ nsCOMPtr<nsIZipWriter> zipWriter = do_CreateInstance("@mozilla.org/zipwriter;1", &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = zipWriter->Open(aOutputFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = AddToZip(zipWriter, aInputFile, EmptyCString());
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // we're done.
+ zipWriter->Close();
+ return rv;
+}
+
+/* static */
+nsresult nsSimpleZipper::AddToZip(nsIZipWriter *aZipWriter,
+ nsIFile *aFile,
+ const nsACString &aPath)
+{
+ // find out the path this file/dir should have in the zip
+ nsCString leafName;
+ aFile->GetNativeLeafName(leafName);
+ nsCString currentPath(aPath);
+ currentPath += leafName;
+
+ bool isDirectory;
+ aFile->IsDirectory(&isDirectory);
+ // append slash for a directory entry
+ if (isDirectory)
+ currentPath.Append('/');
+
+ // add the file or directory entry to the zip
+ nsresult rv = aZipWriter->AddEntryFile(currentPath, nsIZipWriter::COMPRESSION_DEFAULT, aFile, false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // if it's a directory, add all its contents too
+ if (isDirectory) {
+ nsCOMPtr<nsISimpleEnumerator> e;
+ nsresult rv = aFile->GetDirectoryEntries(getter_AddRefs(e));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIDirectoryEnumerator> dirEnumerator = do_QueryInterface(e, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIFile> currentFile;
+ while (NS_SUCCEEDED(dirEnumerator->GetNextFile(getter_AddRefs(currentFile))) && currentFile) {
+ rv = AddToZip(aZipWriter, currentFile, currentPath);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ }
+
+ return NS_OK;
+}
+#endif // XP_MACOSX
+
//
// Class implementation...
//
@@ -168,7 +239,12 @@ NS_IMETHODIMP nsMsgAttachmentHandler::GetAlreadyEncoded(bool* aAlreadyEncoded)
void
nsMsgAttachmentHandler::CleanupTempFile()
{
-/** Mac Stub **/
+#ifdef XP_MACOSX
+ if (mEncodedWorkingFile) {
+ mEncodedWorkingFile->Remove(false);
+ mEncodedWorkingFile = nullptr;
+ }
+#endif // XP_MACOSX
}
void
@@ -473,8 +549,13 @@ FetcherURLDoneCallback(nsresult aStatus,
ma->m_size = totalSize;
if (!aContentType.IsEmpty())
{
- // can't send appledouble on non-macs
+#ifdef XP_MACOSX
+ //Do not change the type if we are dealing with an encoded (e.g., appledouble or zip) file
+ if (!ma->mEncodedWorkingFile)
+#else
+ // can't send appledouble on non-macs
if (!aContentType.EqualsLiteral("multipart/appledouble"))
+#endif
ma->m_type = aContentType;
}
@@ -617,6 +698,15 @@ done:
return rv;
}
+#ifdef XP_MACOSX
+bool nsMsgAttachmentHandler::HasResourceFork(FSRef *fsRef)
+{
+ FSCatalogInfo catalogInfo;
+ OSErr err = FSGetCatalogInfo(fsRef, kFSCatInfoDataSizes + kFSCatInfoRsrcSizes, &catalogInfo, nullptr, nullptr, nullptr);
+ return (err == noErr && catalogInfo.rsrcLogicalSize != 0);
+}
+#endif
+
nsresult
nsMsgAttachmentHandler::SnarfAttachment(nsMsgCompFields *compFields)
{
@@ -657,6 +747,33 @@ nsMsgAttachmentHandler::SnarfAttachment(nsMsgCompFields *compFields)
nsCString sourceURISpec;
rv = mURL->GetSpec(sourceURISpec);
NS_ENSURE_SUCCESS(rv, rv);
+#ifdef XP_MACOSX
+ if (!m_bogus_attachment && StringBeginsWith(sourceURISpec, NS_LITERAL_CSTRING("file://")))
+ {
+ // Unescape the path (i.e. un-URLify it) before making a FSSpec
+ nsAutoCString filePath;
+ filePath.Adopt(nsMsgGetLocalFileFromURL(sourceURISpec.get()));
+ nsAutoCString unescapedFilePath;
+ MsgUnescapeString(filePath, 0, unescapedFilePath);
+
+ nsCOMPtr<nsIFile> sourceFile;
+ NS_NewNativeLocalFile(unescapedFilePath, true, getter_AddRefs(sourceFile));
+ if (!sourceFile)
+ return NS_ERROR_FAILURE;
+
+ // check if it is a bundle. if it is, we'll zip it.
+ // if not, we'll apple encode it (applesingle or appledouble)
+ nsCOMPtr<nsILocalFileMac> macFile(do_QueryInterface(sourceFile));
+ bool isPackage;
+ macFile->IsPackage(&isPackage);
+ if (isPackage)
+ rv = ConvertToZipFile(macFile);
+ else
+ rv = ConvertToAppleEncoding(sourceURISpec, unescapedFilePath, macFile);
+
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+#endif /* XP_MACOSX */
//
// Ok, here we are, we need to fire the URL off and get the data
@@ -676,6 +793,236 @@ nsMsgAttachmentHandler::SnarfAttachment(nsMsgCompFields *compFields)
return fetcher->FireURLRequest(mURL, mTmpFile, mOutFile, FetcherURLDoneCallback, this);
}
+#ifdef XP_MACOSX
+nsresult
+nsMsgAttachmentHandler::ConvertToZipFile(nsILocalFileMac *aSourceFile)
+{
+ // append ".zip" to the real file name
+ nsAutoCString zippedName;
+ nsresult rv = aSourceFile->GetNativeLeafName(zippedName);
+ NS_ENSURE_SUCCESS(rv, rv);
+ zippedName.AppendLiteral(".zip");
+
+ // create a temporary file that we'll work on
+ nsCOMPtr <nsIFile> tmpFile;
+ rv = nsMsgCreateTempFile(zippedName.get(), getter_AddRefs(tmpFile));
+ NS_ENSURE_SUCCESS(rv, rv);
+ mEncodedWorkingFile = do_QueryInterface(tmpFile);
+
+ // point our URL at the zipped temp file
+ NS_NewFileURI(getter_AddRefs(mURL), mEncodedWorkingFile);
+
+ // zip it!
+ rv = nsSimpleZipper::Zip(aSourceFile, mEncodedWorkingFile);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // set some metadata for this attachment, that will affect the MIME headers.
+ m_type = APPLICATION_ZIP;
+ m_realName = zippedName.get();
+
+ return NS_OK;
+}
+
+nsresult
+nsMsgAttachmentHandler::ConvertToAppleEncoding(const nsCString &aFileURI,
+ const nsCString &aFilePath,
+ nsILocalFileMac *aSourceFile)
+{
+ // convert the apple file to AppleDouble first, and then patch the
+ // address in the url.
+
+ //We need to retrieve the file type and creator...
+
+ char fileInfo[32];
+ OSType type, creator;
+
+ nsresult rv = aSourceFile->GetFileType(&type);
+ if (NS_FAILED(rv))
+ return rv;
+ PR_snprintf(fileInfo, sizeof(fileInfo), "%X", type);
+ m_xMacType = fileInfo;
+
+ rv = aSourceFile->GetFileCreator(&creator);
+ if (NS_FAILED(rv))
+ return rv;
+ PR_snprintf(fileInfo, sizeof(fileInfo), "%X", creator);
+ m_xMacCreator = fileInfo;
+
+ FSRef fsRef;
+ aSourceFile->GetFSRef(&fsRef);
+ bool sendResourceFork = HasResourceFork(&fsRef);
+
+ // if we have a resource fork, check the filename extension, maybe we don't need the resource fork!
+ if (sendResourceFork)
+ {
+ nsCOMPtr<nsIURL> fileUrl(do_CreateInstance(NS_STANDARDURL_CONTRACTID));
+ if (fileUrl)
+ {
+ rv = fileUrl->SetSpec(aFileURI);
+ if (NS_SUCCEEDED(rv))
+ {
+ nsAutoCString ext;
+ rv = fileUrl->GetFileExtension(ext);
+ if (NS_SUCCEEDED(rv) && !ext.IsEmpty())
+ {
+ sendResourceFork =
+ PL_strcasecmp(ext.get(), "TXT") &&
+ PL_strcasecmp(ext.get(), "JPG") &&
+ PL_strcasecmp(ext.get(), "GIF") &&
+ PL_strcasecmp(ext.get(), "TIF") &&
+ PL_strcasecmp(ext.get(), "HTM") &&
+ PL_strcasecmp(ext.get(), "HTML") &&
+ PL_strcasecmp(ext.get(), "ART") &&
+ PL_strcasecmp(ext.get(), "XUL") &&
+ PL_strcasecmp(ext.get(), "XML") &&
+ PL_strcasecmp(ext.get(), "CSS") &&
+ PL_strcasecmp(ext.get(), "JS");
+ }
+ }
+ }
+ }
+
+ // Only use appledouble if we aren't uuencoding.
+ if( sendResourceFork )
+ {
+ char *separator;
+
+ separator = mime_make_separator("ad");
+ if (!separator)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsCOMPtr <nsIFile> tmpFile;
+ nsresult rv = nsMsgCreateTempFile("appledouble", getter_AddRefs(tmpFile));
+ if (NS_SUCCEEDED(rv))
+ mEncodedWorkingFile = do_QueryInterface(tmpFile);
+ if (!mEncodedWorkingFile)
+ {
+ PR_FREEIF(separator);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ //
+ // RICHIE_MAC - ok, here's the deal, we have a file that we need
+ // to encode in appledouble encoding for the resource fork and put that
+ // into the mEncodedWorkingFile location. Then, we need to patch the new file
+ // spec into the array and send this as part of the 2 part appledouble/mime
+ // encoded mime part.
+ //
+ AppleDoubleEncodeObject *obj = new (AppleDoubleEncodeObject);
+ if (obj == NULL)
+ {
+ mEncodedWorkingFile = nullptr;
+ PR_FREEIF(separator);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ rv = MsgGetFileStream(mEncodedWorkingFile, getter_AddRefs(obj->fileStream));
+ if (NS_FAILED(rv) || !obj->fileStream)
+ {
+ PR_FREEIF(separator);
+ delete obj;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ char *working_buff = (char *) PR_Malloc(AD_WORKING_BUFF_SIZE);
+ if (!working_buff)
+ {
+ PR_FREEIF(separator);
+ delete obj;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ obj->buff = working_buff;
+ obj->s_buff = AD_WORKING_BUFF_SIZE;
+
+ //
+ // Setup all the need information on the apple double encoder.
+ //
+ ap_encode_init(&(obj->ap_encode_obj), aFilePath.get(), separator);
+
+ int32_t count;
+
+ OSErr status = noErr;
+ m_size = 0;
+ while (status == noErr)
+ {
+ status = ap_encode_next(&(obj->ap_encode_obj), obj->buff, obj->s_buff, &count);
+ if (status == noErr || status == errDone)
+ {
+ //
+ // we got the encode data, so call the next stream to write it to the disk.
+ //
+ uint32_t bytesWritten;
+ obj->fileStream->Write(obj->buff, count, &bytesWritten);
+ if (bytesWritten != (uint32_t) count)
+ status = errFileWrite;
+ }
+ }
+
+ ap_encode_end(&(obj->ap_encode_obj), (status >= 0)); // if this is true, ok, false abort
+ if (obj->fileStream)
+ obj->fileStream->Close();
+
+ PR_FREEIF(obj->buff); /* free the working buff. */
+ PR_FREEIF(obj);
+
+ nsCOMPtr <nsIURI> fileURI;
+ NS_NewFileURI(getter_AddRefs(fileURI), mEncodedWorkingFile);
+
+ nsCOMPtr<nsIFileURL> theFileURL = do_QueryInterface(fileURI, &rv);
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ nsCString newURLSpec;
+ rv = fileURI->GetSpec(newURLSpec);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (newURLSpec.IsEmpty())
+ {
+ PR_FREEIF(separator);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (NS_FAILED(nsMsgNewURL(getter_AddRefs(mURL), newURLSpec.get())))
+ {
+ PR_FREEIF(separator);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ // Now after conversion, also patch the types.
+ char tmp[128];
+ PR_snprintf(tmp, sizeof(tmp), MULTIPART_APPLEDOUBLE ";\r\n boundary=\"%s\"", separator);
+ PR_FREEIF(separator);
+ m_type = tmp;
+ }
+ else
+ {
+ if ( sendResourceFork )
+ {
+ // For now, just do the encoding, but in the old world we would ask the
+ // user about doing this conversion
+ printf("...we could ask the user about this conversion, but for now, nahh..\n");
+ }
+
+ bool useDefault;
+ char *macType, *macEncoding;
+ if (m_type.IsEmpty() || m_type.LowerCaseEqualsLiteral(TEXT_PLAIN))
+ {
+# define TEXT_TYPE 0x54455854 /* the characters 'T' 'E' 'X' 'T' */
+# define text_TYPE 0x74657874 /* the characters 't' 'e' 'x' 't' */
+
+ if (type != TEXT_TYPE && type != text_TYPE)
+ {
+ MacGetFileType(aSourceFile, &useDefault, &macType, &macEncoding);
+ m_type = macType;
+ }
+ }
+ // don't bother to set the types if we failed in getting the file info.
+ }
+
+ return NS_OK;
+}
+#endif // XP_MACOSX
+
nsresult
nsMsgAttachmentHandler::LoadDataFromFile(nsIFile *file, nsString &sigData, bool charsetConversion)
{
diff --git a/mailnews/compose/src/nsMsgAttachmentHandler.h b/mailnews/compose/src/nsMsgAttachmentHandler.h
index 67ac474abd..2034cba032 100644
--- a/mailnews/compose/src/nsMsgAttachmentHandler.h
+++ b/mailnews/compose/src/nsMsgAttachmentHandler.h
@@ -16,6 +16,42 @@
#include "nsAutoPtr.h"
#include "nsIMsgAttachmentHandler.h"
+#ifdef XP_MACOSX
+
+#include "nsMsgAppleDouble.h"
+#include "nsILocalFileMac.h"
+
+class AppleDoubleEncodeObject
+{
+public:
+ appledouble_encode_object ap_encode_obj;
+ char *buff; // the working buff
+ int32_t s_buff; // the working buff size
+ nsCOMPtr <nsIOutputStream> fileStream; // file to hold the encoding
+};
+
+class nsILocalFileMac;
+class nsIZipWriter;
+
+/* Simple utility class that will synchronously zip any file
+ (or folder hierarchy) you give it. */
+class nsSimpleZipper
+{
+ public:
+
+ // Synchronously zips the input file/folder and writes all
+ // data to the output file.
+ static nsresult Zip(nsIFile *aInputFile, nsIFile *aOutputFile);
+
+ private:
+
+ // Recursively adds the file or folder to aZipWriter.
+ static nsresult AddToZip(nsIZipWriter *aZipWriter,
+ nsIFile *aFile,
+ const nsACString &aPath);
+};
+#endif // XP_MACOSX
+
namespace mozilla {
namespace mailnews {
class MimeEncoder;
@@ -59,6 +95,14 @@ private:
bool UseUUEncode_p(void);
void AnalyzeDataChunk (const char *chunk, int32_t chunkSize);
nsresult LoadDataFromFile(nsIFile *file, nsString &sigData, bool charsetConversion); //A similar function already exist in nsMsgCompose!
+#ifdef XP_MACOSX
+ nsresult ConvertToAppleEncoding(const nsCString &aFileSpecURI,
+ const nsCString &aFilePath,
+ nsILocalFileMac *aSourceFile);
+ // zips this attachment and does the work to make this attachment handler handle it properly.
+ nsresult ConvertToZipFile(nsILocalFileMac *aSourceFile);
+ bool HasResourceFork(FSRef *fsRef);
+#endif
//
public:
@@ -69,6 +113,12 @@ public:
nsMsgCompFields *mCompFields; // Message composition fields for the sender
bool m_bogus_attachment; // This is to catch problem children...
+#ifdef XP_MACOSX
+ // if we need to encode this file into for example an appledouble, or zip file,
+ // this file is our working file. currently only needed on mac.
+ nsCOMPtr<nsIFile> mEncodedWorkingFile;
+#endif
+
nsCString m_xMacType; // Mac file type
nsCString m_xMacCreator; // Mac file creator
diff --git a/mailnews/compose/src/nsMsgSend.cpp b/mailnews/compose/src/nsMsgSend.cpp
index e328a9e21d..919d9bfc54 100644
--- a/mailnews/compose/src/nsMsgSend.cpp
+++ b/mailnews/compose/src/nsMsgSend.cpp
@@ -2088,7 +2088,9 @@ nsMsgComposeAndSend::AddCompFieldLocalAttachments()
if (NS_SUCCEEDED(rv) && !fileExt.IsEmpty()) {
nsAutoCString type;
mimeFinder->GetTypeFromExtension(fileExt, type);
+ #ifndef XP_MACOSX
if (!type.Equals("multipart/appledouble")) // can't do apple double on non-macs
+ #endif
m_attachments[newLoc]->m_type = type;
}
}
@@ -2103,7 +2105,9 @@ nsMsgComposeAndSend::AddCompFieldLocalAttachments()
if (NS_SUCCEEDED(rv) && !fileExt.IsEmpty()) {
nsAutoCString type;
mimeFinder->GetTypeFromExtension(fileExt, type);
+ #ifndef XP_MACOSX
if (!type.Equals("multipart/appledouble")) // can't do apple double on non-macs
+ #endif
m_attachments[newLoc]->m_type = type;
// rtf and vcs files may look like text to sniffers,
// but they're not human readable.
diff --git a/mailnews/imap/src/nsIMAPBodyShell.cpp b/mailnews/imap/src/nsIMAPBodyShell.cpp
index b81978cc7b..087fe20337 100644
--- a/mailnews/imap/src/nsIMAPBodyShell.cpp
+++ b/mailnews/imap/src/nsIMAPBodyShell.cpp
@@ -724,8 +724,27 @@ bool nsIMAPBodypartLeaf::ShouldFetchInline(nsIMAPBodyShell *aShell)
return false; // we can leave it on the server
}
+#ifdef XP_MACOSX
+ // If it is either applesingle, or a resource fork for appledouble
+ if (!PL_strcasecmp(m_contentType, "application/applefile"))
+ {
+ // if it is appledouble
+ if (m_parentPart->GetType() == IMAP_BODY_MULTIPART &&
+ !PL_strcasecmp(m_parentPart->GetBodySubType(), "appledouble"))
+ {
+ // This is the resource fork of a multipart/appledouble.
+ // We inherit the inline attributes of the parent,
+ // which was derived from its OTHER child. (The data fork.)
+ return m_parentPart->ShouldFetchInline(aShell);
+ }
+ else // it is applesingle
+ {
+ return false; // we can leave it on the server
+ }
+ }
+#endif // XP_MACOSX
- // Leave out parts with type application/(*)
+ // Leave out parts with type application/*
if (!PL_strcasecmp(m_bodyType, "APPLICATION") && // If it is of type "application"
PL_strncasecmp(m_bodySubType, "x-pkcs7", 7) // and it's not a signature (signatures are inline)
)
diff --git a/mailnews/import/applemail/src/moz.build b/mailnews/import/applemail/src/moz.build
new file mode 100644
index 0000000000..fafbebc990
--- /dev/null
+++ b/mailnews/import/applemail/src/moz.build
@@ -0,0 +1,14 @@
+# 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/.
+
+SOURCES += [
+ 'nsAppleMailImport.cpp',
+]
+
+SOURCES += [
+ 'nsEmlxHelperUtils.mm',
+]
+
+FINAL_LIBRARY = 'import'
+
diff --git a/mailnews/import/applemail/src/nsAppleMailImport.cpp b/mailnews/import/applemail/src/nsAppleMailImport.cpp
new file mode 100644
index 0000000000..3097b7df5e
--- /dev/null
+++ b/mailnews/import/applemail/src/nsAppleMailImport.cpp
@@ -0,0 +1,623 @@
+/* -*- 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 "nsStringGlue.h"
+#include "nsCOMPtr.h"
+#include "nsISupportsPrimitives.h"
+#include "nsIImportService.h"
+#include "nsIImportMailboxDescriptor.h"
+#include "nsIImportGeneric.h"
+#include "nsIFile.h"
+#include "nsIStringBundle.h"
+#include "nsIMsgFolder.h"
+#include "nsIMsgHdr.h"
+#include "nsIMsgPluggableStore.h"
+#include "nsIMutableArray.h"
+#include "nsNetUtil.h"
+#include "nsMsgUtils.h"
+#include "mozilla/Services.h"
+
+#include "nsEmlxHelperUtils.h"
+#include "nsAppleMailImport.h"
+#include "nsIOutputStream.h"
+
+PRLogModuleInfo *APPLEMAILLOGMODULE = nullptr;
+
+// some hard-coded strings
+#define DEFAULT_MAIL_FOLDER "~/Library/Mail/"
+#define POP_MBOX_SUFFIX ".mbox"
+#define IMAP_MBOX_SUFFIX ".imapmbox"
+
+// stringbundle URI
+#define APPLEMAIL_MSGS_URL "chrome://messenger/locale/appleMailImportMsgs.properties"
+
+// magic constants
+#define kAccountMailboxID 1234
+
+nsAppleMailImportModule::nsAppleMailImportModule()
+{
+ // Init logging module.
+ if (!APPLEMAILLOGMODULE)
+ APPLEMAILLOGMODULE = PR_NewLogModule("APPLEMAILIMPORTLOG");
+
+ IMPORT_LOG0("nsAppleMailImportModule Created");
+
+ nsCOMPtr<nsIStringBundleService> bundleService =
+ mozilla::services::GetStringBundleService();
+ if (bundleService)
+ bundleService->CreateBundle(APPLEMAIL_MSGS_URL, getter_AddRefs(mBundle));
+}
+
+
+nsAppleMailImportModule::~nsAppleMailImportModule()
+{
+ IMPORT_LOG0("nsAppleMailImportModule Deleted");
+}
+
+
+NS_IMPL_ISUPPORTS(nsAppleMailImportModule, nsIImportModule)
+
+
+NS_IMETHODIMP nsAppleMailImportModule::GetName(char16_t **aName)
+{
+ return mBundle ?
+ mBundle->GetStringFromName(u"ApplemailImportName", aName) : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP nsAppleMailImportModule::GetDescription(char16_t **aName)
+{
+ return mBundle ?
+ mBundle->GetStringFromName(u"ApplemailImportDescription", aName) : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP nsAppleMailImportModule::GetSupports(char **aSupports)
+{
+ NS_ENSURE_ARG_POINTER(aSupports);
+ *aSupports = strdup(NS_IMPORT_MAIL_STR);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAppleMailImportModule::GetSupportsUpgrade(bool *aUpgrade)
+{
+ NS_ENSURE_ARG_POINTER(aUpgrade);
+ *aUpgrade = false;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAppleMailImportModule::GetImportInterface(const char *aImportType, nsISupports **aInterface)
+{
+ NS_ENSURE_ARG_POINTER(aImportType);
+ NS_ENSURE_ARG_POINTER(aInterface);
+ *aInterface = nullptr;
+ nsresult rv = NS_ERROR_NOT_AVAILABLE;
+
+ if (!strcmp(aImportType, "mail")) {
+ nsCOMPtr<nsIImportMail> mail(do_CreateInstance(NS_APPLEMAILIMPL_CONTRACTID, &rv));
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsIImportService> impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsIImportGeneric> generic;
+ rv = impSvc->CreateNewGenericMail(getter_AddRefs(generic));
+ if (NS_SUCCEEDED(rv)) {
+ nsAutoString name;
+ rv = mBundle->GetStringFromName(u"ApplemailImportName", getter_Copies(name));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsISupportsString> nameString(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+ nameString->SetData(name);
+
+ generic->SetData("name", nameString);
+ generic->SetData("mailInterface", mail);
+
+ generic.forget(aInterface);
+ }
+ }
+ }
+ }
+
+ return rv;
+}
+
+#pragma mark -
+
+nsAppleMailImportMail::nsAppleMailImportMail() : mProgress(0), mCurDepth(0)
+{
+ IMPORT_LOG0("nsAppleMailImportMail created");
+}
+
+nsresult nsAppleMailImportMail::Initialize()
+{
+ nsCOMPtr<nsIStringBundleService> bundleService =
+ mozilla::services::GetStringBundleService();
+ NS_ENSURE_TRUE(bundleService, NS_ERROR_UNEXPECTED);
+
+ return bundleService->CreateBundle(APPLEMAIL_MSGS_URL, getter_AddRefs(mBundle));
+}
+
+nsAppleMailImportMail::~nsAppleMailImportMail()
+{
+ IMPORT_LOG0("nsAppleMailImportMail destroyed");
+}
+
+NS_IMPL_ISUPPORTS(nsAppleMailImportMail, nsIImportMail)
+
+NS_IMETHODIMP nsAppleMailImportMail::GetDefaultLocation(nsIFile **aLocation, bool *aFound, bool *aUserVerify)
+{
+ NS_ENSURE_ARG_POINTER(aFound);
+ NS_ENSURE_ARG_POINTER(aLocation);
+ NS_ENSURE_ARG_POINTER(aUserVerify);
+
+ *aLocation = nullptr;
+ *aFound = false;
+ *aUserVerify = true;
+
+ // try to find current user's top-level Mail folder
+ nsCOMPtr<nsIFile> mailFolder(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
+ if (mailFolder) {
+ nsresult rv = mailFolder->InitWithNativePath(NS_LITERAL_CSTRING(DEFAULT_MAIL_FOLDER));
+ if (NS_SUCCEEDED(rv)) {
+ *aFound = true;
+ *aUserVerify = false;
+ mailFolder.forget(aLocation);
+ }
+ }
+
+ return NS_OK;
+}
+
+// this is the method that initiates all searching for mailboxes.
+// it will assume that it has a directory like ~/Library/Mail/
+NS_IMETHODIMP nsAppleMailImportMail::FindMailboxes(nsIFile *aMailboxFile, nsIArray **aResult)
+{
+ NS_ENSURE_ARG_POINTER(aMailboxFile);
+ NS_ENSURE_ARG_POINTER(aResult);
+
+ IMPORT_LOG0("FindMailboxes for Apple mail invoked");
+
+ bool exists = false;
+ nsresult rv = aMailboxFile->Exists(&exists);
+ if (NS_FAILED(rv) || !exists)
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIImportService> importService(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIMutableArray> resultsArray(do_CreateInstance(NS_ARRAY_CONTRACTID, &rv));
+ if (!resultsArray)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mCurDepth = 1;
+
+ // 1. look for accounts with mailboxes
+ FindAccountMailDirs(aMailboxFile, resultsArray, importService);
+ mCurDepth--;
+
+ if (NS_SUCCEEDED(rv)) {
+ // 2. look for "global" mailboxes, that don't belong to any specific account. they are inside the
+ // root's Mailboxes/ folder
+ nsCOMPtr<nsIFile> mailboxesDir(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));
+ if (NS_SUCCEEDED(rv)) {
+ mailboxesDir->InitWithFile(aMailboxFile);
+ rv = mailboxesDir->Append(NS_LITERAL_STRING("Mailboxes"));
+ if (NS_SUCCEEDED(rv)) {
+ IMPORT_LOG0("Looking for global Apple mailboxes");
+
+ mCurDepth++;
+ rv = FindMboxDirs(mailboxesDir, resultsArray, importService);
+ mCurDepth--;
+ }
+ }
+ }
+
+ if (NS_SUCCEEDED(rv) && resultsArray)
+ resultsArray.forget(aResult);
+
+ return rv;
+}
+
+// operates on the Mail/ directory root, trying to find accounts (which are folders named something like "POP-hwaara@gmail.com")
+// and add their .mbox dirs
+void nsAppleMailImportMail::FindAccountMailDirs(nsIFile *aRoot, nsIMutableArray *aMailboxDescs, nsIImportService *aImportService)
+{
+ nsCOMPtr<nsISimpleEnumerator> directoryEnumerator;
+ nsresult rv = aRoot->GetDirectoryEntries(getter_AddRefs(directoryEnumerator));
+ if (NS_FAILED(rv))
+ return;
+
+ bool hasMore = false;
+ while (NS_SUCCEEDED(directoryEnumerator->HasMoreElements(&hasMore)) && hasMore) {
+
+ // get the next file entry
+ nsCOMPtr<nsIFile> currentEntry;
+ {
+ nsCOMPtr<nsISupports> rawSupports;
+ directoryEnumerator->GetNext(getter_AddRefs(rawSupports));
+ if (!rawSupports)
+ continue;
+ currentEntry = do_QueryInterface(rawSupports);
+ if (!currentEntry)
+ continue;
+ }
+
+ // make sure it's a directory
+ bool isDirectory = false;
+ currentEntry->IsDirectory(&isDirectory);
+
+ if (isDirectory) {
+ // now let's see if it's an account folder. if so, we want to traverse it for .mbox children
+ nsAutoString folderName;
+ currentEntry->GetLeafName(folderName);
+ bool isAccountFolder = false;
+
+ if (StringBeginsWith(folderName, NS_LITERAL_STRING("POP-"))) {
+ // cut off "POP-" prefix so we get a nice folder name
+ folderName.Cut(0, 4);
+ isAccountFolder = true;
+ }
+ else if (StringBeginsWith(folderName, NS_LITERAL_STRING("IMAP-"))) {
+ // cut off "IMAP-" prefix so we get a nice folder name
+ folderName.Cut(0, 5);
+ isAccountFolder = true;
+ }
+
+ if (isAccountFolder) {
+ IMPORT_LOG1("Found account: %s\n", NS_ConvertUTF16toUTF8(folderName).get());
+
+ // create a mailbox for this account, so we get a parent for "Inbox", "Sent Messages", etc.
+ nsCOMPtr<nsIImportMailboxDescriptor> desc;
+ nsresult rv = aImportService->CreateNewMailboxDescriptor(getter_AddRefs(desc));
+ desc->SetSize(1);
+ desc->SetDepth(mCurDepth);
+ desc->SetDisplayName(folderName.get());
+ desc->SetIdentifier(kAccountMailboxID);
+
+ nsCOMPtr<nsIFile> mailboxDescFile;
+ rv = desc->GetFile(getter_AddRefs(mailboxDescFile));
+ if (!mailboxDescFile)
+ continue;
+
+ mailboxDescFile->InitWithFile(currentEntry);
+
+ // add this mailbox descriptor to the list
+ aMailboxDescs->AppendElement(desc, false);
+
+ // now add all the children mailboxes
+ mCurDepth++;
+ FindMboxDirs(currentEntry, aMailboxDescs, aImportService);
+ mCurDepth--;
+ }
+ }
+ }
+}
+
+// adds the specified file as a mailboxdescriptor to the array
+nsresult nsAppleMailImportMail::AddMboxDir(nsIFile *aFolder, nsIMutableArray *aMailboxDescs, nsIImportService *aImportService)
+{
+ nsAutoString folderName;
+ aFolder->GetLeafName(folderName);
+
+ // cut off the suffix, if any, or prefix if this is an account folder.
+ if (StringEndsWith(folderName, NS_LITERAL_STRING(POP_MBOX_SUFFIX)))
+ folderName.SetLength(folderName.Length()-5);
+ else if (StringEndsWith(folderName, NS_LITERAL_STRING(IMAP_MBOX_SUFFIX)))
+ folderName.SetLength(folderName.Length()-9);
+ else if (StringBeginsWith(folderName, NS_LITERAL_STRING("POP-")))
+ folderName.Cut(4, folderName.Length());
+ else if (StringBeginsWith(folderName, NS_LITERAL_STRING("IMAP-")))
+ folderName.Cut(5, folderName.Length());
+
+ nsCOMPtr<nsIImportMailboxDescriptor> desc;
+ nsresult rv = aImportService->CreateNewMailboxDescriptor(getter_AddRefs(desc));
+ if (NS_SUCCEEDED(rv)) {
+ // find out number of messages in this .mbox
+ uint32_t numMessages = 0;
+ {
+ // move to the .mbox's Messages folder
+ nsCOMPtr<nsIFile> messagesFolder;
+ aFolder->Clone(getter_AddRefs(messagesFolder));
+ nsresult rv = messagesFolder->Append(NS_LITERAL_STRING("Messages"));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // count the number of messages in this folder. it sucks that we have to iterate through the folder
+ // but XPCOM doesn't give us any way to just get the file count, unfortunately. :-(
+ nsCOMPtr<nsISimpleEnumerator> dirEnumerator;
+ messagesFolder->GetDirectoryEntries(getter_AddRefs(dirEnumerator));
+ if (dirEnumerator) {
+ bool hasMore = false;
+ while (NS_SUCCEEDED(dirEnumerator->HasMoreElements(&hasMore)) && hasMore) {
+ nsCOMPtr<nsISupports> rawSupports;
+ dirEnumerator->GetNext(getter_AddRefs(rawSupports));
+ if (!rawSupports)
+ continue;
+
+ nsCOMPtr<nsIFile> file(do_QueryInterface(rawSupports));
+ if (file) {
+ bool isFile = false;
+ file->IsFile(&isFile);
+ if (isFile)
+ numMessages++;
+ }
+ }
+ }
+ }
+
+ desc->SetSize(numMessages);
+ desc->SetDisplayName(folderName.get());
+ desc->SetDepth(mCurDepth);
+
+ IMPORT_LOG3("Will import %s with approx %d messages, depth is %d", NS_ConvertUTF16toUTF8(folderName).get(), numMessages, mCurDepth);
+
+ // XXX: this is silly. there's no setter for the mailbox descriptor's file, so we need to get it, and then modify it.
+ nsCOMPtr<nsIFile> mailboxDescFile;
+ rv = desc->GetFile(getter_AddRefs(mailboxDescFile));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (mailboxDescFile)
+ mailboxDescFile->InitWithFile(aFolder);
+
+ // add this mailbox descriptor to the list
+ aMailboxDescs->AppendElement(desc, false);
+ }
+
+ return NS_OK;
+}
+
+// Starts looking for .mbox dirs in the specified dir. The .mbox dirs contain messages and can be considered leafs in a tree of
+// nested mailboxes (subfolders).
+//
+// If a mailbox has sub-mailboxes, they are contained in a sibling folder with the same name without the ".mbox" part.
+// example:
+// MyParentMailbox.mbox/
+// MyParentMailbox/
+// MyChildMailbox.mbox/
+// MyOtherChildMailbox.mbox/
+//
+nsresult nsAppleMailImportMail::FindMboxDirs(nsIFile *aFolder, nsIMutableArray *aMailboxDescs, nsIImportService *aImportService)
+{
+ NS_ENSURE_ARG_POINTER(aFolder);
+ NS_ENSURE_ARG_POINTER(aMailboxDescs);
+ NS_ENSURE_ARG_POINTER(aImportService);
+
+ // make sure this is a directory.
+ bool isDir = false;
+ if (NS_FAILED(aFolder->IsDirectory(&isDir)) || !isDir)
+ return NS_ERROR_FAILURE;
+
+ // iterate through the folder contents
+ nsCOMPtr<nsISimpleEnumerator> directoryEnumerator;
+ nsresult rv = aFolder->GetDirectoryEntries(getter_AddRefs(directoryEnumerator));
+ if (NS_FAILED(rv) || !directoryEnumerator)
+ return rv;
+
+ bool hasMore = false;
+ while (NS_SUCCEEDED(directoryEnumerator->HasMoreElements(&hasMore)) && hasMore) {
+
+ // get the next file entry
+ nsCOMPtr<nsIFile> currentEntry;
+ {
+ nsCOMPtr<nsISupports> rawSupports;
+ directoryEnumerator->GetNext(getter_AddRefs(rawSupports));
+ if (!rawSupports)
+ continue;
+ currentEntry = do_QueryInterface(rawSupports);
+ if (!currentEntry)
+ continue;
+ }
+
+ // we only care about directories...
+ if (NS_FAILED(currentEntry->IsDirectory(&isDir)) || !isDir)
+ continue;
+
+ // now find out if this is a .mbox dir
+ nsAutoString currentFolderName;
+ if (NS_SUCCEEDED(currentEntry->GetLeafName(currentFolderName)) &&
+ (StringEndsWith(currentFolderName, NS_LITERAL_STRING(POP_MBOX_SUFFIX)) ||
+ StringEndsWith(currentFolderName, NS_LITERAL_STRING(IMAP_MBOX_SUFFIX)))) {
+ IMPORT_LOG1("Adding .mbox dir: %s", NS_ConvertUTF16toUTF8(currentFolderName).get());
+
+ // add this .mbox
+ rv = AddMboxDir(currentEntry, aMailboxDescs, aImportService);
+ if (NS_FAILED(rv)) {
+ IMPORT_LOG1("Couldn't add .mbox for import: %s ... continuing anyway", NS_ConvertUTF16toUTF8(currentFolderName).get());
+ continue;
+ }
+
+ // see if this .mbox dir has any sub-mailboxes
+ nsAutoString siblingMailboxDirPath;
+ currentEntry->GetPath(siblingMailboxDirPath);
+
+ // cut off suffix
+ if (StringEndsWith(siblingMailboxDirPath, NS_LITERAL_STRING(IMAP_MBOX_SUFFIX)))
+ siblingMailboxDirPath.SetLength(siblingMailboxDirPath.Length()-9);
+ else if (StringEndsWith(siblingMailboxDirPath, NS_LITERAL_STRING(POP_MBOX_SUFFIX)))
+ siblingMailboxDirPath.SetLength(siblingMailboxDirPath.Length()-5);
+
+ IMPORT_LOG1("trying to locate a '%s'", NS_ConvertUTF16toUTF8(siblingMailboxDirPath).get());
+ nsCOMPtr<nsIFile> siblingMailboxDir(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));
+ if (NS_FAILED(rv))
+ continue;
+
+ rv = siblingMailboxDir->InitWithPath(siblingMailboxDirPath);
+ bool reallyExists = false;
+ siblingMailboxDir->Exists(&reallyExists);
+
+ if (NS_SUCCEEDED(rv) && reallyExists) {
+ IMPORT_LOG1("Found what looks like an .mbox container: %s", NS_ConvertUTF16toUTF8(currentFolderName).get());
+
+ // traverse this folder for other .mboxes
+ mCurDepth++;
+ FindMboxDirs(siblingMailboxDir, aMailboxDescs, aImportService);
+ mCurDepth--;
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsAppleMailImportMail::ImportMailbox(nsIImportMailboxDescriptor *aMailbox,
+ nsIMsgFolder *aDstFolder,
+ char16_t **aErrorLog,
+ char16_t **aSuccessLog, bool *aFatalError)
+{
+ nsAutoString errorLog, successLog;
+
+ // reset progress
+ mProgress = 0;
+
+ nsAutoString mailboxName;
+ aMailbox->GetDisplayName(getter_Copies(mailboxName));
+
+ nsCOMPtr<nsIFile> mboxFolder;
+ nsresult rv = aMailbox->GetFile(getter_AddRefs(mboxFolder));
+ if (NS_FAILED(rv) || !mboxFolder) {
+ ReportStatus(u"ApplemailImportMailboxConverterror", mailboxName, errorLog);
+ SetLogs(successLog, errorLog, aSuccessLog, aErrorLog);
+ return NS_ERROR_FAILURE;
+ }
+
+ // if we're an account mailbox, nothing do. if we're a real mbox
+ // then we've got some messages to import!
+ uint32_t mailboxIdentifier;
+ aMailbox->GetIdentifier(&mailboxIdentifier);
+
+ if (mailboxIdentifier != kAccountMailboxID) {
+ // move to the .mbox's Messages folder
+ nsCOMPtr<nsIFile> messagesFolder;
+ mboxFolder->Clone(getter_AddRefs(messagesFolder));
+ rv = messagesFolder->Append(NS_LITERAL_STRING("Messages"));
+ if (NS_FAILED(rv)) {
+ // even if there are no messages, it might still be a valid mailbox, or even
+ // a parent for other mailboxes.
+ //
+ // just indicate that we're done, using the same number that we used to estimate
+ // number of messages earlier.
+ uint32_t finalSize;
+ aMailbox->GetSize(&finalSize);
+ mProgress = finalSize;
+
+ // report that we successfully imported this mailbox
+ ReportStatus(u"ApplemailImportMailboxSuccess", mailboxName, successLog);
+ SetLogs(successLog, errorLog, aSuccessLog, aErrorLog);
+ return NS_OK;
+ }
+
+ // let's import the messages!
+ nsCOMPtr<nsISimpleEnumerator> directoryEnumerator;
+ rv = messagesFolder->GetDirectoryEntries(getter_AddRefs(directoryEnumerator));
+ if (NS_FAILED(rv)) {
+ ReportStatus(u"ApplemailImportMailboxConvertError", mailboxName, errorLog);
+ SetLogs(successLog, errorLog, aSuccessLog, aErrorLog);
+ return NS_ERROR_FAILURE;
+ }
+
+ // prepare an outstream to the destination file
+ nsCOMPtr<nsIMsgPluggableStore> msgStore;
+ rv = aDstFolder->GetMsgStore(getter_AddRefs(msgStore));
+ if (!msgStore || NS_FAILED(rv)) {
+ ReportStatus(u"ApplemailImportMailboxConverterror", mailboxName, errorLog);
+ SetLogs(successLog, errorLog, aSuccessLog, aErrorLog);
+ return NS_ERROR_FAILURE;
+ }
+
+ bool hasMore = false;
+ nsCOMPtr<nsIOutputStream> outStream;
+
+ while (NS_SUCCEEDED(directoryEnumerator->HasMoreElements(&hasMore)) && hasMore) {
+ // get the next file entry
+ nsCOMPtr<nsIFile> currentEntry;
+ {
+ nsCOMPtr<nsISupports> rawSupports;
+ directoryEnumerator->GetNext(getter_AddRefs(rawSupports));
+ if (!rawSupports)
+ continue;
+ currentEntry = do_QueryInterface(rawSupports);
+ if (!currentEntry)
+ continue;
+ }
+
+ // make sure it's an .emlx file
+ bool isFile = false;
+ currentEntry->IsFile(&isFile);
+ if (!isFile)
+ continue;
+
+ nsAutoString leafName;
+ currentEntry->GetLeafName(leafName);
+ if (!StringEndsWith(leafName, NS_LITERAL_STRING(".emlx")))
+ continue;
+
+ nsCOMPtr<nsIMsgDBHdr> msgHdr;
+ bool reusable;
+ rv = msgStore->GetNewMsgOutputStream(aDstFolder, getter_AddRefs(msgHdr),
+ &reusable,
+ getter_AddRefs(outStream));
+ if (NS_FAILED(rv))
+ break;
+
+ // add the data to the mbox stream
+ if (NS_SUCCEEDED(nsEmlxHelperUtils::AddEmlxMessageToStream(currentEntry, outStream))) {
+ mProgress++;
+ msgStore->FinishNewMessage(outStream, msgHdr);
+ }
+ else {
+ msgStore->DiscardNewMessage(outStream, msgHdr);
+ break;
+ }
+ if (!reusable)
+ outStream->Close();
+ }
+ if (outStream)
+ outStream->Close();
+ }
+ // just indicate that we're done, using the same number that we used to estimate
+ // number of messages earlier.
+ uint32_t finalSize;
+ aMailbox->GetSize(&finalSize);
+ mProgress = finalSize;
+
+ // report that we successfully imported this mailbox
+ ReportStatus(u"ApplemailImportMailboxSuccess", mailboxName, successLog);
+ SetLogs(successLog, errorLog, aSuccessLog, aErrorLog);
+
+ return NS_OK;
+}
+
+void nsAppleMailImportMail::ReportStatus(const char16_t* aErrorName, nsString &aName,
+ nsAString &aStream)
+{
+ // get (and format, if needed) the error string from the bundle
+ nsAutoString outString;
+ const char16_t *fmt = { aName.get() };
+ nsresult rv = mBundle->FormatStringFromName(aErrorName, &fmt, 1, getter_Copies(outString));
+ // write it out the stream
+ if (NS_SUCCEEDED(rv)) {
+ aStream.Append(outString);
+ aStream.Append(char16_t('\n'));
+ }
+}
+
+void nsAppleMailImportMail::SetLogs(const nsAString &aSuccess, const nsAString &aError, char16_t **aOutSuccess, char16_t **aOutError)
+{
+ if (aOutError && !*aOutError)
+ *aOutError = ToNewUnicode(aError);
+ if (aOutSuccess && !*aOutSuccess)
+ *aOutSuccess = ToNewUnicode(aSuccess);
+}
+
+NS_IMETHODIMP nsAppleMailImportMail::GetImportProgress(uint32_t *aDoneSoFar)
+{
+ NS_ENSURE_ARG_POINTER(aDoneSoFar);
+ *aDoneSoFar = mProgress;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAppleMailImportMail::TranslateFolderName(const nsAString &aFolderName, nsAString &aResult)
+{
+ aResult = aFolderName;
+ return NS_OK;
+}
diff --git a/mailnews/import/applemail/src/nsAppleMailImport.h b/mailnews/import/applemail/src/nsAppleMailImport.h
new file mode 100644
index 0000000000..b906aecf56
--- /dev/null
+++ b/mailnews/import/applemail/src/nsAppleMailImport.h
@@ -0,0 +1,78 @@
+/* -*- 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/. */
+
+#ifndef nsAppleMailImport_h___
+#define nsAppleMailImport_h___
+
+#include "mozilla/Logging.h"
+#include "nsIImportModule.h"
+#include "nsCOMPtr.h"
+#include "nsIStringBundle.h"
+#include "nsIImportMail.h"
+
+// logging facilities
+extern PRLogModuleInfo *APPLEMAILLOGMODULE;
+
+#define IMPORT_LOG0(x) MOZ_LOG(APPLEMAILLOGMODULE, mozilla::LogLevel::Debug, (x))
+#define IMPORT_LOG1(x, y) MOZ_LOG(APPLEMAILLOGMODULE, mozilla::LogLevel::Debug, (x, y))
+#define IMPORT_LOG2(x, y, z) MOZ_LOG(APPLEMAILLOGMODULE, mozilla::LogLevel::Debug, (x, y, z))
+#define IMPORT_LOG3(a, b, c, d) MOZ_LOG(APPLEMAILLOGMODULE, mozilla::LogLevel::Debug, (a, b, c, d))
+
+#define NS_APPLEMAILIMPL_CID \
+{ 0x9117a1ea, 0xe012, 0x43b5, { 0xa0, 0x20, 0xcb, 0x8a, 0x66, 0xcc, 0x09, 0xe1 } }
+
+#define NS_APPLEMAILIMPORT_CID \
+{ 0x6d3f101c, 0x70ec, 0x4e04, { 0xb6, 0x8d, 0x99, 0x08, 0xd1, 0xae, 0xdd, 0xf3 } }
+
+#define NS_APPLEMAILIMPL_CONTRACTID "@mozilla.org/import/import-appleMailImpl;1"
+
+#define kAppleMailSupportsString "mail"
+
+class nsIImportService;
+class nsIMutableArray;
+
+class nsAppleMailImportModule : public nsIImportModule
+{
+ public:
+
+ nsAppleMailImportModule();
+
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIIMPORTMODULE
+
+ private:
+ virtual ~nsAppleMailImportModule();
+
+ nsCOMPtr<nsIStringBundle> mBundle;
+};
+
+class nsAppleMailImportMail : public nsIImportMail
+{
+ public:
+
+ nsAppleMailImportMail();
+
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIIMPORTMAIL
+
+ nsresult Initialize();
+
+ private:
+ virtual ~nsAppleMailImportMail();
+
+ void FindAccountMailDirs(nsIFile *aRoot, nsIMutableArray *aMailboxDescs, nsIImportService *aImportService);
+ nsresult FindMboxDirs(nsIFile *aFolder, nsIMutableArray *aMailboxDescs, nsIImportService *aImportService);
+ nsresult AddMboxDir(nsIFile *aFolder, nsIMutableArray *aMailboxDescs, nsIImportService *aImportService);
+
+ // aInfoString is the format to a "foo %s" string. It may be NULL if the error string needs no such format.
+ void ReportStatus(const char16_t* aErrorName, nsString &aName, nsAString &aStream);
+ static void SetLogs(const nsAString& success, const nsAString& error, char16_t **aOutErrorLog, char16_t **aSuccessLog);
+
+ nsCOMPtr<nsIStringBundle> mBundle;
+ uint32_t mProgress;
+ uint16_t mCurDepth;
+};
+
+#endif /* nsAppleMailImport_h___ */
diff --git a/mailnews/import/applemail/src/nsEmlxHelperUtils.h b/mailnews/import/applemail/src/nsEmlxHelperUtils.h
new file mode 100644
index 0000000000..728b725b60
--- /dev/null
+++ b/mailnews/import/applemail/src/nsEmlxHelperUtils.h
@@ -0,0 +1,55 @@
+/* -*- 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/. */
+
+#ifndef nsEmlxHelperUtils_h___
+#define nsEmlxHelperUtils_h___
+
+#include "nscore.h"
+#include "nsStringGlue.h"
+
+class nsIOutputStream;
+class nsIFile;
+
+class nsEmlxHelperUtils {
+ /* All emlx messages have a "flags" number in the metadata.
+ These are the masks to decode that, found via http://jwz.livejournal.com/505711.html */
+ enum EmlxMetadataMask {
+ kRead = 1 << 0, // read
+ // 1 << 1, // deleted
+ kAnswered = 1 << 2, // answered
+ // 1 << 3, // encrypted
+ kFlagged = 1 << 4, // flagged
+ // 1 << 5, // recent
+ // 1 << 6, // draft
+ // 1 << 7, // initial (no longer used)
+ kForwarded = 1 << 8, // forwarded
+ // 1 << 9, // redirected
+ // 3F << 10, // attachment count (6 bits)
+ // 7F << 16, // priority level (7 bits)
+ // 1 << 23, // signed
+ // 1 << 24, // is junk
+ // 1 << 25, // is not junk
+ // 1 << 26, // font size delta 7 (3 bits)
+ // 1 << 29, // junk mail level recorded
+ // 1 << 30, // highlight text in toc
+ // 1 << 31 // (unused)
+ };
+
+ // This method will scan the raw EMLX message buffer for "dangerous" so-called "From-lines" that we need to escape.
+ // If it needs to modify any lines, it will return a non-NULL aOutBuffer. If aOutBuffer is NULL, no modification needed
+ // to be made.
+ static nsresult ConvertToMboxRD(const char *aMessageBufferStart, const char *aMessageBufferEnd, nsCString &aOutBuffer);
+
+ // returns an int representing the X-Mozilla-Status flags set (e.g. "read", "flagged") converted from EMLX flags.
+ static nsresult ConvertToMozillaStatusFlags(const char *aXMLBufferStart, const char *aXMLBufferEnd, uint32_t *aMozillaStatusFlags);
+
+ public:
+
+ // add an .emlx message to the mbox output
+ static nsresult AddEmlxMessageToStream(nsIFile *aEmlxFile, nsIOutputStream *aOutoutStream);
+
+};
+
+#endif // nsEmlxHelperUtils_h___
diff --git a/mailnews/import/applemail/src/nsEmlxHelperUtils.mm b/mailnews/import/applemail/src/nsEmlxHelperUtils.mm
new file mode 100644
index 0000000000..d2feb166e6
--- /dev/null
+++ b/mailnews/import/applemail/src/nsEmlxHelperUtils.mm
@@ -0,0 +1,240 @@
+/* -*- 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 "nsEmlxHelperUtils.h"
+#include "nsIFileStreams.h"
+#include "nsIBufferedStreams.h"
+#include "nsIOutputStream.h"
+#include "nsNetUtil.h"
+#include "nsCOMPtr.h"
+#include "nsObjCExceptions.h"
+#include "nsMsgMessageFlags.h"
+#include "nsMsgLocalFolderHdrs.h"
+#include "msgCore.h"
+#include "nsTArray.h"
+#include "nsAppleMailImport.h"
+#include "prprf.h"
+#include "nsIFile.h"
+
+#import <Cocoa/Cocoa.h>
+
+
+nsresult nsEmlxHelperUtils::ConvertToMozillaStatusFlags(const char *aXMLBufferStart,
+ const char *aXMLBufferEnd,
+ uint32_t *aMozillaStatusFlags)
+{
+ // create a NSData wrapper around the buffer, so we can use the Cocoa call below
+ NSData *metadata =
+ [[[NSData alloc] initWithBytesNoCopy:(void *)aXMLBufferStart length:(aXMLBufferEnd-aXMLBufferStart) freeWhenDone:NO] autorelease];
+
+ // get the XML data as a dictionary
+ NSPropertyListFormat format;
+ id plist = [NSPropertyListSerialization propertyListWithData:metadata
+ options:NSPropertyListImmutable
+ format:&format
+ error:NULL];
+
+ if (!plist)
+ return NS_ERROR_FAILURE;
+
+ // find the <flags>...</flags> value and convert to int
+ const uint32_t emlxMessageFlags = [[(NSDictionary *)plist objectForKey:@"flags"] intValue];
+
+ if (emlxMessageFlags == 0)
+ return NS_ERROR_FAILURE;
+
+ if (emlxMessageFlags & nsEmlxHelperUtils::kRead)
+ *aMozillaStatusFlags |= nsMsgMessageFlags::Read;
+ if (emlxMessageFlags & nsEmlxHelperUtils::kForwarded)
+ *aMozillaStatusFlags |= nsMsgMessageFlags::Forwarded;
+ if (emlxMessageFlags & nsEmlxHelperUtils::kAnswered)
+ *aMozillaStatusFlags |= nsMsgMessageFlags::Replied;
+ if (emlxMessageFlags & nsEmlxHelperUtils::kFlagged)
+ *aMozillaStatusFlags |= nsMsgMessageFlags::Marked;
+
+ return NS_OK;
+}
+
+nsresult nsEmlxHelperUtils::ConvertToMboxRD(const char *aMessageBufferStart, const char *aMessageBufferEnd, nsCString &aOutBuffer)
+{
+ nsTArray<const char *> foundFromLines;
+
+ const char *cur = aMessageBufferStart;
+ while (cur < aMessageBufferEnd) {
+
+ const char *foundFromStr = strnstr(cur, "From ", aMessageBufferEnd-cur);
+
+ if (foundFromStr) {
+ // skip all prepending '>' chars
+ const char *fromLineStart = foundFromStr;
+ while (fromLineStart-- >= aMessageBufferStart) {
+ if (*fromLineStart == '\n' || fromLineStart == aMessageBufferStart) {
+ if (fromLineStart > aMessageBufferStart)
+ fromLineStart++;
+ foundFromLines.AppendElement(fromLineStart);
+ break;
+ }
+ else if (*fromLineStart != '>')
+ break;
+ }
+
+ // advance past the last found From string.
+ cur = foundFromStr + 5;
+
+ // look for more From lines.
+ continue;
+ }
+
+ break;
+ }
+
+ // go through foundFromLines
+ if (foundFromLines.Length()) {
+
+ const char *chunkStart = aMessageBufferStart;
+ for (unsigned i=0; i<foundFromLines.Length(); ++i) {
+ aOutBuffer.Append(chunkStart, (foundFromLines[i]-chunkStart));
+ aOutBuffer.Append(NS_LITERAL_CSTRING(">"));
+
+ chunkStart = foundFromLines[i];
+ }
+ aOutBuffer.Append(chunkStart, (aMessageBufferEnd - chunkStart));
+ }
+
+ return NS_OK;
+}
+
+nsresult nsEmlxHelperUtils::AddEmlxMessageToStream(nsIFile *aMessage, nsIOutputStream *aOut)
+{
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+ // needed to be sure autoreleased objects are released too, which they might not
+ // in a C++ environment where the main event loop has no autorelease pool (e.g on a XPCOM thread)
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ nsresult rv = NS_ERROR_FAILURE;
+
+ nsAutoCString path;
+ aMessage->GetNativePath(path);
+
+ NSData *data = [NSData dataWithContentsOfFile:[NSString stringWithUTF8String:path.get()]];
+ if (!data) {
+ [pool release];
+ return NS_ERROR_FAILURE;
+ }
+
+ char *startOfMessageData = NULL;
+ uint32_t actualBytesWritten = 0;
+
+ // The anatomy of an EMLX file:
+ //
+ // -------------------------------
+ // < A number describing how many bytes ahead there is message data >
+ // < Message data >
+ // < XML metadata for this message >
+ // -------------------------------
+
+ // read the first line of the emlx file, which is a number of how many bytes ahead the actual
+ // message data is.
+ uint64_t numberOfBytesToRead = strtol((char *)[data bytes], &startOfMessageData, 10);
+ if (numberOfBytesToRead <= 0 || !startOfMessageData) {
+ [pool release];
+ return NS_ERROR_FAILURE;
+ }
+
+ // skip whitespace
+ while (*startOfMessageData == ' ' ||
+ *startOfMessageData == '\n' ||
+ *startOfMessageData == '\r' ||
+ *startOfMessageData == '\t')
+ ++startOfMessageData;
+
+ NS_NAMED_LITERAL_CSTRING(kBogusFromLine, "From \n");
+ NS_NAMED_LITERAL_CSTRING(kEndOfMessage, "\n\n");
+
+ // write the bogus "From " line which is a magic separator in the mbox format
+ rv = aOut->Write(kBogusFromLine.get(), kBogusFromLine.Length(), &actualBytesWritten);
+ if (NS_FAILED(rv)) {
+ [pool release];
+ return rv;
+ }
+
+ // now read the XML metadata, so we can extract info like which flags (read? replied? flagged? etc) this message has.
+ const char *startOfXMLMetadata = startOfMessageData + numberOfBytesToRead;
+ const char *endOfXMLMetadata = (char *)[data bytes] + [data length];
+
+ uint32_t x_mozilla_flags = 0;
+ ConvertToMozillaStatusFlags(startOfXMLMetadata, endOfXMLMetadata, &x_mozilla_flags);
+
+ // write the X-Mozilla-Status header according to which flags we've gathered above.
+ uint32_t dummyRv;
+ nsAutoCString buf(PR_smprintf(X_MOZILLA_STATUS_FORMAT MSG_LINEBREAK, x_mozilla_flags));
+ NS_ASSERTION(!buf.IsEmpty(), "printf error with X-Mozilla-Status header");
+ if (buf.IsEmpty()) {
+ [pool release];
+ return rv;
+ }
+
+ rv = aOut->Write(buf.get(), buf.Length(), &dummyRv);
+ if (NS_FAILED(rv)) {
+ [pool release];
+ return rv;
+ }
+
+ // write out X-Mozilla-Keywords header as well to reserve some space for it
+ // in the mbox file.
+ rv = aOut->Write(X_MOZILLA_KEYWORDS, X_MOZILLA_KEYWORDS_LEN, &dummyRv);
+ if (NS_FAILED(rv)) {
+ [pool release];
+ return rv;
+ }
+
+ // write out empty X-Mozilla_status2 header
+ buf.Adopt(PR_smprintf(X_MOZILLA_STATUS2_FORMAT MSG_LINEBREAK, 0));
+ NS_ASSERTION(!buf.IsEmpty(), "printf error with X-Mozilla-Status2 header");
+ if (buf.IsEmpty()) {
+ [pool release];
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ rv = aOut->Write(buf.get(), buf.Length(), &dummyRv);
+ if (NS_FAILED(rv)) {
+ [pool release];
+ return rv;
+ }
+
+ // do any conversion needed for the mbox data to be valid mboxrd.
+ nsCString convertedData;
+ rv = ConvertToMboxRD(startOfMessageData, (startOfMessageData + numberOfBytesToRead), convertedData);
+ if (NS_FAILED(rv)) {
+ [pool release];
+ return rv;
+ }
+
+ // write the actual message data.
+ if (convertedData.IsEmpty())
+ rv = aOut->Write(startOfMessageData, (uint32_t)numberOfBytesToRead, &actualBytesWritten);
+ else {
+ IMPORT_LOG1("Escaped From-lines in %s!", path.get());
+ rv = aOut->Write(convertedData.get(), convertedData.Length(), &actualBytesWritten);
+ }
+
+ if (NS_FAILED(rv)) {
+ [pool release];
+ return rv;
+ }
+
+ NS_ASSERTION(actualBytesWritten == (convertedData.IsEmpty() ? numberOfBytesToRead : convertedData.Length()),
+ "Didn't write as many bytes as expected for .emlx file?");
+
+ // add newlines to denote the end of this message in the mbox
+ rv = aOut->Write(kEndOfMessage.get(), kEndOfMessage.Length(), &actualBytesWritten);
+
+ [pool release];
+
+ return rv;
+
+ NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
diff --git a/mailnews/import/build/nsImportModule.cpp b/mailnews/import/build/nsImportModule.cpp
index 813271b08f..f8f3814e6e 100644
--- a/mailnews/import/build/nsImportModule.cpp
+++ b/mailnews/import/build/nsImportModule.cpp
@@ -33,6 +33,16 @@ NS_DEFINE_NAMED_CID(NS_TEXTIMPORT_CID);
NS_DEFINE_NAMED_CID(NS_VCARDIMPORT_CID);
////////////////////////////////////////////////////////////////////////////////
+// Apple Mail import Include Files
+////////////////////////////////////////////////////////////////////////////////
+#if defined(XP_MACOSX)
+#include "nsAppleMailImport.h"
+
+NS_DEFINE_NAMED_CID(NS_APPLEMAILIMPORT_CID);
+NS_DEFINE_NAMED_CID(NS_APPLEMAILIMPL_CID);
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
// outlook import Include Files
////////////////////////////////////////////////////////////////////////////////
#ifdef XP_WIN
@@ -76,6 +86,14 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsTextImport)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsVCardImport)
////////////////////////////////////////////////////////////////////////////////
+// apple mail import factories
+////////////////////////////////////////////////////////////////////////////////
+#if defined(XP_MACOSX)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsAppleMailImportModule)
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsAppleMailImportMail, Initialize)
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
// outlook import factories
////////////////////////////////////////////////////////////////////////////////
#ifdef XP_WIN
@@ -103,6 +121,9 @@ static const mozilla::Module::CategoryEntry kMailNewsImportCategories[] = {
{ "mailnewsimport", "{1DB469A0-8B00-11d3-A206-00A0CC26DA63}", kOutlookSupportsString },
#endif
#endif
+#if defined(XP_MACOSX)
+ { "mailnewsimport", "{6d3f101c-70ec-4e04-b68d-9908d1aeddf3}", kAppleMailSupportsString },
+#endif
{ NULL }
};
@@ -111,6 +132,11 @@ const mozilla::Module::CIDEntry kMailNewsImportCIDs[] = {
{ &kNS_IMPORTMIMEENCODE_CID, false, NULL, nsIImportMimeEncodeImplConstructor },
{ &kNS_TEXTIMPORT_CID, false, NULL, nsTextImportConstructor },
{ &kNS_VCARDIMPORT_CID, false, NULL, nsVCardImportConstructor },
+#if defined(XP_MACOSX)
+ { &kNS_APPLEMAILIMPORT_CID, false, NULL, nsAppleMailImportModuleConstructor },
+ { &kNS_APPLEMAILIMPL_CID, false, NULL, nsAppleMailImportMailConstructor },
+#endif
+
#ifdef XP_WIN
{ &kNS_WMIMPORT_CID, false, NULL, nsWMImportConstructor },
{ &kNS_BECKYIMPORT_CID, false, NULL, nsBeckyImportConstructor },
@@ -126,6 +152,11 @@ const mozilla::Module::ContractIDEntry kMailNewsImportContracts[] = {
{ "@mozilla.org/import/import-mimeencode;1", &kNS_IMPORTMIMEENCODE_CID },
{ "@mozilla.org/import/import-text;1", &kNS_TEXTIMPORT_CID },
{ "@mozilla.org/import/import-vcard;1", &kNS_VCARDIMPORT_CID },
+#if defined(XP_MACOSX)
+ { "@mozilla.org/import/import-applemail;1", &kNS_APPLEMAILIMPORT_CID },
+ { NS_APPLEMAILIMPL_CONTRACTID, &kNS_APPLEMAILIMPL_CID },
+#endif
+
#ifdef XP_WIN
{ "@mozilla.org/import/import-wm;1", &kNS_WMIMPORT_CID },
{ "@mozilla.org/import/import-becky;1", &kNS_BECKYIMPORT_CID },
diff --git a/mailnews/import/content/importDialog.xul b/mailnews/import/content/importDialog.xul
index 1223a12635..383585f83e 100644
--- a/mailnews/import/content/importDialog.xul
+++ b/mailnews/import/content/importDialog.xul
@@ -15,7 +15,11 @@
<window xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="OnLoadImportDialog()"
+#ifdef XP_MACOSX
+ style="width: &window.macWidth; !important;"
+#else
style="width: &window.width; !important;"
+#endif
title="&importDialog.windowTitle;">
<stringbundle id="bundle_importMsgs" src="chrome://messenger/locale/importMsgs.properties"/>
diff --git a/mailnews/jar.mn b/mailnews/jar.mn
index 8b850ecb91..71539e9aa0 100644
--- a/mailnews/jar.mn
+++ b/mailnews/jar.mn
@@ -131,6 +131,8 @@ messenger.jar:
content/messenger/dateFormat.js (base/content/dateFormat.js)
content/messenger/shutdownWindow.xul (base/content/shutdownWindow.xul)
content/messenger/shutdownWindow.js (base/content/shutdownWindow.js)
+#ifndef XP_MACOSX
content/messenger/newmailalert.css (base/content/newmailalert.css)
content/messenger/newmailalert.js (base/content/newmailalert.js)
content/messenger/newmailalert.xul (base/content/newmailalert.xul)
+#endif
diff --git a/mailnews/mailnews.js b/mailnews/mailnews.js
index ae172305d2..49ac33827e 100644
--- a/mailnews/mailnews.js
+++ b/mailnews/mailnews.js
@@ -696,7 +696,11 @@ pref("mail.biff.alert.show_subject", true);
pref("mail.biff.alert.show_sender", true);
pref("mail.biff.alert.preview_length", 40);
+#ifdef XP_MACOSX
+pref("mail.biff.play_sound", false);
+#else
pref("mail.biff.play_sound", true);
+#endif
// 0 == default system sound, 1 == user specified wav
pref("mail.biff.play_sound.type", 0);
// _moz_mailbeep is a magic key, for the default sound.
@@ -706,6 +710,8 @@ pref("mail.biff.show_alert", true);
#ifdef XP_WIN
pref("mail.biff.show_tray_icon", true);
pref("mail.biff.show_balloon", false);
+#elifdef XP_MACOSX
+pref("mail.biff.animate_dock_icon", false);
#elifdef XP_UNIX
pref("mail.biff.use_system_alert", false);
#endif
@@ -718,6 +724,13 @@ pref("mail.biff.add_interval_jitter", true);
pref("mail.biff.on_new_window", true);
#endif
+#ifdef XP_MACOSX
+// If true, the number used in the Mac OS X dock notification will be the
+// the number of "new" messages, as per the classic Thunderbird definition.
+// Defaults to false, which notifies about the number of unread messages.
+pref("mail.biff.use_new_count_in_mac_dock", false);
+#endif
+
// For feed account serverType=rss sound on biff; if true, mail.biff.play_sound.* settings are used.
pref("mail.feed.play_sound", false);
@@ -834,6 +847,15 @@ pref("ldap_2.servers.oe.description", "chrome://messenger/locale/addressbook/add
pref("ldap_2.servers.oe.dirType", 3);
#endif
#endif
+#ifdef XP_MACOSX
+pref("ldap_2.servers.osx.uri", "moz-abosxdirectory:///");
+pref("ldap_2.servers.osx.description", "chrome://messenger/locale/addressbook/addressBook.properties");
+pref("ldap_2.servers.osx.dirType", 3);
+pref("mail.notification.sound", "");
+pref("mail.notification.count.inbox_only", true);
+// Work around bug 482811 by disabling slow script warning for chrome scripts on Mac
+pref("dom.max_chrome_script_run_time", 0);
+#endif
// gtk2 (*nix) lacks transparent/translucent drag support (bug 376238), so we
// want to disable it so people can see where they are dragging things.
diff --git a/mailnews/mime/src/mimeebod.cpp b/mailnews/mime/src/mimeebod.cpp
index ee66c40ca2..2ca056feb8 100644
--- a/mailnews/mime/src/mimeebod.cpp
+++ b/mailnews/mime/src/mimeebod.cpp
@@ -21,6 +21,10 @@
MimeDefClass(MimeExternalBody, MimeExternalBodyClass,
mimeExternalBodyClass, &MIME_SUPERCLASS);
+#ifdef XP_MACOSX
+extern MimeObjectClass mimeMultipartAppleDoubleClass;
+#endif
+
static int MimeExternalBody_initialize (MimeObject *);
static void MimeExternalBody_finalize (MimeObject *);
static int MimeExternalBody_parse_line (const char *, int32_t, MimeObject *);
@@ -248,6 +252,12 @@ MimeExternalBody_parse_eof (MimeObject *obj, bool abort_p)
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p);
if (status < 0) return status;
+#ifdef XP_MACOSX
+ if (obj->parent && mime_typep(obj->parent,
+ (MimeObjectClass*) &mimeMultipartAppleDoubleClass))
+ goto done;
+#endif /* XP_MACOSX */
+
if (!abort_p &&
obj->output_p &&
obj->options &&
@@ -415,6 +425,10 @@ FAIL:
PR_FREEIF(subj);
}
+#ifdef XP_MACOSX
+done:
+#endif
+
return status;
}
diff --git a/mailnews/mime/src/mimemapl.cpp b/mailnews/mime/src/mimemapl.cpp
index c7363ceff1..449d80ac08 100644
--- a/mailnews/mime/src/mimemapl.cpp
+++ b/mailnews/mime/src/mimemapl.cpp
@@ -55,6 +55,19 @@ MimeMultipartAppleDouble_parse_begin (MimeObject *obj)
NS_ASSERTION(obj->options->state->first_data_written_p, "first data not written");
}
+#ifdef XP_MACOSX
+ if (obj->options && obj->options->state)
+ {
+// obj->options->state->separator_suppressed_p = true;
+ goto done;
+ }
+ /*
+ * It would be nice to not showing the resource fork links
+ * if we are displaying inline. But, there is no way we could
+ * know ahead of time that we could display the data fork and
+ * the data fork is always hidden on MAC platform.
+ */
+#endif
/* If we're writing this object as HTML, then emit a link for the
multipart/appledouble part (both links) that looks just like the
links that MimeExternalObject emits for external leaf parts.
@@ -143,6 +156,10 @@ GOTTA STILL DO THIS FOR QUOTING!
if (status < 0) return status;
}
+#ifdef XP_MACOSX
+done:
+#endif
+
return 0;
}
@@ -159,8 +176,13 @@ MimeMultipartAppleDouble_output_child_p(MimeObject *obj, MimeObject *child)
if (cont->nchildren >= 1 && cont->children[0] == child && child->content_type &&
!PL_strcasecmp(child->content_type, APPLICATION_APPLEFILE))
{
- /* Don't emit the resources fork. */
+#ifdef XP_MACOSX
+ if (obj->output_p && obj->options && obj->options->write_html_p) //output HTML
+ return false;
+#else
+ /* if we are not on a Macintosh, don't emitte the resources fork at all. */
return false;
+#endif
}
return true;
diff --git a/mailnews/mime/src/mimemult.cpp b/mailnews/mime/src/mimemult.cpp
index c92cc44dcf..4695ba9910 100644
--- a/mailnews/mime/src/mimemult.cpp
+++ b/mailnews/mime/src/mimemult.cpp
@@ -16,6 +16,10 @@
#include "nsMimeTypes.h"
#include <ctype.h>
+#ifdef XP_MACOSX
+ extern MimeObjectClass mimeMultipartAppleDoubleClass;
+#endif
+
#define MIME_SUPERCLASS mimeContainerClass
MimeDefClass(MimeMultipart, MimeMultipartClass,
mimeMultipartClass, &MIME_SUPERCLASS);
@@ -488,6 +492,19 @@ MimeMultipart_create_child(MimeObject *obj)
{
status = body->clazz->parse_begin(body);
+#ifdef XP_MACOSX
+ /* if we are saving an apple double attachment, we need to set correctly the conten type of the channel */
+ if (mime_typep(obj, (MimeObjectClass *) &mimeMultipartAppleDoubleClass))
+ {
+ mime_stream_data *msd = (mime_stream_data *)body->options->stream_closure;
+ if (!body->options->write_html_p && body->content_type && !PL_strcasecmp(body->content_type, APPLICATION_APPLEFILE))
+ {
+ if (msd && msd->channel)
+ msd->channel->SetContentType(NS_LITERAL_CSTRING(APPLICATION_APPLEFILE));
+ }
+ }
+#endif
+
if (status < 0) return status;
}
diff --git a/mailnews/moz.build b/mailnews/moz.build
index 55b80c443a..6e75c8012e 100644
--- a/mailnews/moz.build
+++ b/mailnews/moz.build
@@ -23,6 +23,11 @@ DIRS += [
'news',
]
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
+ DIRS += [
+ 'import/applemail/src',
+ ]
+
if CONFIG['OS_ARCH'] == 'WINNT':
DIRS += [ 'import/becky/src' ]