summaryrefslogtreecommitdiffstats
path: root/mailnews/import/becky/src
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2019-11-03 00:17:46 -0400
committerMatt A. Tobin <email@mattatobin.com>2019-11-03 00:17:46 -0400
commit302bf1b523012e11b60425d6eee1221ebc2724eb (patch)
treeb191a895f8716efcbe42f454f37597a545a6f421 /mailnews/import/becky/src
parent21b3f6247403c06f85e1f45d219f87549862198f (diff)
downloadUXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.gz
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.lz
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.xz
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.zip
Issue #1258 - Part 1: Import mailnews, ldap, and mork from comm-esr52.9.1
Diffstat (limited to 'mailnews/import/becky/src')
-rw-r--r--mailnews/import/becky/src/moz.build16
-rw-r--r--mailnews/import/becky/src/nsBeckyAddressBooks.cpp383
-rw-r--r--mailnews/import/becky/src/nsBeckyAddressBooks.h35
-rw-r--r--mailnews/import/becky/src/nsBeckyFilters.cpp793
-rw-r--r--mailnews/import/becky/src/nsBeckyFilters.h77
-rw-r--r--mailnews/import/becky/src/nsBeckyImport.cpp168
-rw-r--r--mailnews/import/becky/src/nsBeckyImport.h36
-rw-r--r--mailnews/import/becky/src/nsBeckyMail.cpp641
-rw-r--r--mailnews/import/becky/src/nsBeckyMail.h45
-rw-r--r--mailnews/import/becky/src/nsBeckySettings.cpp471
-rw-r--r--mailnews/import/becky/src/nsBeckySettings.h52
-rw-r--r--mailnews/import/becky/src/nsBeckyStringBundle.cpp74
-rw-r--r--mailnews/import/becky/src/nsBeckyStringBundle.h33
-rw-r--r--mailnews/import/becky/src/nsBeckyUtils.cpp334
-rw-r--r--mailnews/import/becky/src/nsBeckyUtils.h37
15 files changed, 3195 insertions, 0 deletions
diff --git a/mailnews/import/becky/src/moz.build b/mailnews/import/becky/src/moz.build
new file mode 100644
index 000000000..ce7651aa8
--- /dev/null
+++ b/mailnews/import/becky/src/moz.build
@@ -0,0 +1,16 @@
+# vim: set filetype=python:
+# 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/.
+
+UNIFIED_SOURCES += [
+ 'nsBeckyAddressBooks.cpp',
+ 'nsBeckyFilters.cpp',
+ 'nsBeckyImport.cpp',
+ 'nsBeckyMail.cpp',
+ 'nsBeckySettings.cpp',
+ 'nsBeckyStringBundle.cpp',
+ 'nsBeckyUtils.cpp',
+]
+
+FINAL_LIBRARY = 'import'
diff --git a/mailnews/import/becky/src/nsBeckyAddressBooks.cpp b/mailnews/import/becky/src/nsBeckyAddressBooks.cpp
new file mode 100644
index 000000000..86654ac0e
--- /dev/null
+++ b/mailnews/import/becky/src/nsBeckyAddressBooks.cpp
@@ -0,0 +1,383 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 "nsCOMPtr.h"
+#include "nsComponentManagerUtils.h"
+#include "nsServiceManagerUtils.h"
+#include "nsIFile.h"
+#include "nsISimpleEnumerator.h"
+#include "nsIDirectoryEnumerator.h"
+#include "nsIMutableArray.h"
+#include "nsStringGlue.h"
+#include "nsAbBaseCID.h"
+#include "nsIAbManager.h"
+#include "nsIImportService.h"
+#include "nsIImportABDescriptor.h"
+#include "nsMsgUtils.h"
+#include "nsIStringBundle.h"
+#include "nsVCardAddress.h"
+
+#include "nsBeckyAddressBooks.h"
+#include "nsBeckyStringBundle.h"
+#include "nsBeckyUtils.h"
+
+NS_IMPL_ISUPPORTS(nsBeckyAddressBooks, nsIImportAddressBooks)
+
+nsresult
+nsBeckyAddressBooks::Create(nsIImportAddressBooks **aImport)
+{
+ NS_ENSURE_ARG_POINTER(aImport);
+
+ *aImport = new nsBeckyAddressBooks();
+
+ NS_ADDREF(*aImport);
+ return NS_OK;
+}
+
+nsBeckyAddressBooks::nsBeckyAddressBooks()
+: mReadBytes(0)
+{
+}
+
+nsBeckyAddressBooks::~nsBeckyAddressBooks()
+{
+}
+
+NS_IMETHODIMP
+nsBeckyAddressBooks::GetSupportsMultiple(bool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = true;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBeckyAddressBooks::GetAutoFind(char16_t **aDescription,
+ bool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(aDescription);
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ *aDescription =
+ nsBeckyStringBundle::GetStringByName(u"BeckyImportDescription");
+ *_retval = false;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBeckyAddressBooks::GetNeedsFieldMap(nsIFile *aLocation, bool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ *_retval = false;
+ return NS_OK;
+}
+
+nsresult
+nsBeckyAddressBooks::FindAddressBookDirectory(nsIFile **aAddressBookDirectory)
+{
+ nsCOMPtr<nsIFile> userDirectory;
+ nsresult rv = nsBeckyUtils::FindUserDirectory(getter_AddRefs(userDirectory));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = userDirectory->Append(NS_LITERAL_STRING("AddrBook"));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool exists = false;
+ rv = userDirectory->Exists(&exists);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!exists)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ bool isDirectory = false;
+ rv = userDirectory->IsDirectory(&isDirectory);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!isDirectory)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ userDirectory.forget(aAddressBookDirectory);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBeckyAddressBooks::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;
+
+ if (NS_SUCCEEDED(nsBeckyAddressBooks::FindAddressBookDirectory(aLocation))) {
+ *aFound = true;
+ *aUserVerify = false;
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckyAddressBooks::CreateAddressBookDescriptor(nsIImportABDescriptor **aDescriptor)
+{
+ nsresult rv;
+ nsCOMPtr<nsIImportService> importService = do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return importService->CreateNewABDescriptor(aDescriptor);
+}
+
+bool
+nsBeckyAddressBooks::IsAddressBookFile(nsIFile *aFile)
+{
+ if (!aFile)
+ return false;
+
+ nsresult rv;
+ bool isFile = false;
+ rv = aFile->IsFile(&isFile);
+ if (NS_FAILED(rv) && !isFile)
+ return false;
+
+ nsAutoString name;
+ rv = aFile->GetLeafName(name);
+ return StringEndsWith(name, NS_LITERAL_STRING(".bab"));
+}
+
+bool
+nsBeckyAddressBooks::HasAddressBookFile(nsIFile *aDirectory)
+{
+ if (!aDirectory)
+ return false;
+
+ nsresult rv;
+ bool isDirectory = false;
+ rv = aDirectory->IsDirectory(&isDirectory);
+ if (NS_FAILED(rv) || !isDirectory)
+ return false;
+
+ nsCOMPtr<nsISimpleEnumerator> entries;
+ rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
+ NS_ENSURE_SUCCESS(rv, false);
+
+ bool more;
+ nsCOMPtr<nsISupports> entry;
+ while (NS_SUCCEEDED(entries->HasMoreElements(&more)) && more) {
+ rv = entries->GetNext(getter_AddRefs(entry));
+ NS_ENSURE_SUCCESS(rv, false);
+
+ nsCOMPtr<nsIFile> file = do_QueryInterface(entry, &rv);
+ NS_ENSURE_SUCCESS(rv, false);
+ if (IsAddressBookFile(file))
+ return true;
+ }
+
+ return false;
+}
+
+uint32_t
+nsBeckyAddressBooks::CountAddressBookSize(nsIFile *aDirectory)
+{
+ if (!aDirectory)
+ return 0;
+
+ nsresult rv;
+ bool isDirectory = false;
+ rv = aDirectory->IsDirectory(&isDirectory);
+ if (NS_FAILED(rv) || !isDirectory)
+ return 0;
+
+ nsCOMPtr<nsISimpleEnumerator> entries;
+ rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
+ NS_ENSURE_SUCCESS(rv, 0);
+
+ uint32_t total = 0;
+ bool more;
+ nsCOMPtr<nsISupports> entry;
+ while (NS_SUCCEEDED(entries->HasMoreElements(&more)) && more) {
+ rv = entries->GetNext(getter_AddRefs(entry));
+ NS_ENSURE_SUCCESS(rv, 0);
+
+ nsCOMPtr<nsIFile> file = do_QueryInterface(entry, &rv);
+ NS_ENSURE_SUCCESS(rv, 0);
+
+ int64_t size;
+ file->GetFileSize(&size);
+ if (total + size > std::numeric_limits<uint32_t>::max())
+ return std::numeric_limits<uint32_t>::max();
+
+ total += static_cast<uint32_t>(size);
+ }
+
+ return total;
+}
+
+nsresult
+nsBeckyAddressBooks::AppendAddressBookDescriptor(nsIFile *aEntry,
+ nsIMutableArray *aCollected)
+{
+ NS_ENSURE_ARG_POINTER(aCollected);
+
+ if (!HasAddressBookFile(aEntry))
+ return NS_OK;
+
+ nsresult rv;
+ nsCOMPtr<nsIImportABDescriptor> descriptor;
+ rv = CreateAddressBookDescriptor(getter_AddRefs(descriptor));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint32_t size = CountAddressBookSize(aEntry);
+ descriptor->SetSize(size);
+ descriptor->SetAbFile(aEntry);
+
+ nsAutoString name;
+ aEntry->GetLeafName(name);
+ descriptor->SetPreferredName(name);
+
+ return aCollected->AppendElement(descriptor, false);
+}
+
+nsresult
+nsBeckyAddressBooks::CollectAddressBooks(nsIFile *aTarget,
+ nsIMutableArray *aCollected)
+{
+ nsresult rv = AppendAddressBookDescriptor(aTarget, aCollected);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsISimpleEnumerator> entries;
+ rv = aTarget->GetDirectoryEntries(getter_AddRefs(entries));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool more;
+ nsCOMPtr<nsISupports> entry;
+ while (NS_SUCCEEDED(entries->HasMoreElements(&more)) && more) {
+ rv = entries->GetNext(getter_AddRefs(entry));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIFile> file = do_QueryInterface(entry, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool isDirectory = false;
+ rv = file->IsDirectory(&isDirectory);
+ if (NS_SUCCEEDED(rv) && isDirectory)
+ rv = CollectAddressBooks(file, aCollected);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBeckyAddressBooks::FindAddressBooks(nsIFile *aLocation,
+ nsIArray **_retval)
+{
+ NS_ENSURE_ARG_POINTER(aLocation);
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ nsresult rv;
+ nsCOMPtr<nsIMutableArray> array(do_CreateInstance(NS_ARRAY_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool isDirectory = false;
+ rv = aLocation->IsDirectory(&isDirectory);
+ if (NS_FAILED(rv) || !isDirectory)
+ return NS_ERROR_FAILURE;
+
+ rv = CollectAddressBooks(aLocation, array);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ array.forget(_retval);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBeckyAddressBooks::InitFieldMap(nsIImportFieldMap *aFieldMap)
+{
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsBeckyAddressBooks::ImportAddressBook(nsIImportABDescriptor *aSource,
+ nsIAddrDatabase *aDestination,
+ nsIImportFieldMap *aFieldMap,
+ nsISupports *aSupportService,
+ char16_t **aErrorLog,
+ char16_t **aSuccessLog,
+ bool *aFatalError)
+{
+ NS_ENSURE_ARG_POINTER(aSource);
+ NS_ENSURE_ARG_POINTER(aDestination);
+ NS_ENSURE_ARG_POINTER(aErrorLog);
+ NS_ENSURE_ARG_POINTER(aSuccessLog);
+ NS_ENSURE_ARG_POINTER(aFatalError);
+
+ mReadBytes = 0;
+
+ nsCOMPtr<nsIFile> file;
+ nsresult rv = aSource->GetAbFile(getter_AddRefs(file));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsISimpleEnumerator> entries;
+ rv = file->GetDirectoryEntries(getter_AddRefs(entries));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool more;
+ nsCOMPtr<nsISupports> entry;
+ nsAutoString error;
+ while (NS_SUCCEEDED(entries->HasMoreElements(&more)) && more) {
+ rv = entries->GetNext(getter_AddRefs(entry));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIFile> file = do_QueryInterface(entry, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!IsAddressBookFile(file))
+ continue;
+
+ bool aborted = false;
+ nsAutoString name;
+ aSource->GetPreferredName(name);
+ nsVCardAddress vcard;
+ rv = vcard.ImportAddresses(&aborted, name.get(), file, aDestination, error, &mReadBytes);
+ if (NS_FAILED(rv)) {
+ break;
+ }
+ }
+
+ if (!error.IsEmpty())
+ *aErrorLog = ToNewUnicode(error);
+ else
+ *aSuccessLog = nsBeckyStringBundle::GetStringByName(u"BeckyImportAddressSuccess");
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsBeckyAddressBooks::GetImportProgress(uint32_t *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = mReadBytes;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBeckyAddressBooks::SetSampleLocation(nsIFile *aLocation)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBeckyAddressBooks::GetSampleData(int32_t aRecordNumber,
+ bool *aRecordExists,
+ char16_t **_retval)
+{
+ return NS_ERROR_FAILURE;
+}
+
diff --git a/mailnews/import/becky/src/nsBeckyAddressBooks.h b/mailnews/import/becky/src/nsBeckyAddressBooks.h
new file mode 100644
index 000000000..83eb4c895
--- /dev/null
+++ b/mailnews/import/becky/src/nsBeckyAddressBooks.h
@@ -0,0 +1,35 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 nsBeckyAddressBooks_h___
+#define nsBeckyAddressBooks_h___
+
+#include "nsIImportAddressBooks.h"
+
+class nsBeckyAddressBooks final : public nsIImportAddressBooks
+{
+public:
+ nsBeckyAddressBooks();
+ static nsresult Create(nsIImportAddressBooks **aImport);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIIMPORTADDRESSBOOKS
+
+private:
+ virtual ~nsBeckyAddressBooks();
+
+ uint32_t mReadBytes;
+
+ nsresult CollectAddressBooks(nsIFile *aTarget, nsIMutableArray *aCollected);
+ nsresult FindAddressBookDirectory(nsIFile **aAddressBookDirectory);
+ nsresult AppendAddressBookDescriptor(nsIFile *aEntry,
+ nsIMutableArray *aCollected);
+ uint32_t CountAddressBookSize(nsIFile *aDirectory);
+ bool HasAddressBookFile(nsIFile *aDirectory);
+ bool IsAddressBookFile(nsIFile *aFile);
+ nsresult CreateAddressBookDescriptor(nsIImportABDescriptor **aDescriptor);
+};
+
+#endif /* nsBeckyAddressBooks_h___ */
diff --git a/mailnews/import/becky/src/nsBeckyFilters.cpp b/mailnews/import/becky/src/nsBeckyFilters.cpp
new file mode 100644
index 000000000..517a18014
--- /dev/null
+++ b/mailnews/import/becky/src/nsBeckyFilters.cpp
@@ -0,0 +1,793 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 "nsArrayUtils.h"
+#include "nsILineInputStream.h"
+#include "nsIStringBundle.h"
+#include "nsComponentManagerUtils.h"
+#include "nsServiceManagerUtils.h"
+#include "nsIMsgFilter.h"
+#include "nsIMsgFilterList.h"
+#include "nsIMsgAccountManager.h"
+#include "nsIMsgAccount.h"
+#include "nsIMsgSearchTerm.h"
+#include "nsIMsgFolder.h"
+#include "nsCOMPtr.h"
+#include "nsMsgSearchCore.h"
+#include "nsMsgBaseCID.h"
+#include "nsMsgUtils.h"
+#include "msgCore.h"
+
+#include "nsBeckyFilters.h"
+#include "nsBeckyStringBundle.h"
+#include "nsBeckyUtils.h"
+
+NS_IMPL_ISUPPORTS(nsBeckyFilters, nsIImportFilters)
+
+nsresult
+nsBeckyFilters::Create(nsIImportFilters **aImport)
+{
+ NS_ENSURE_ARG_POINTER(aImport);
+
+ *aImport = new nsBeckyFilters();
+
+ NS_ADDREF(*aImport);
+ return NS_OK;
+}
+
+nsBeckyFilters::nsBeckyFilters()
+: mLocation(nullptr),
+ mServer(nullptr),
+ mConvertedFile(nullptr)
+{
+}
+
+nsBeckyFilters::~nsBeckyFilters()
+{
+}
+
+nsresult
+nsBeckyFilters::GetDefaultFilterLocation(nsIFile **aFile)
+{
+ NS_ENSURE_ARG_POINTER(aFile);
+
+ nsresult rv;
+ nsCOMPtr<nsIFile> filterDir;
+ rv = nsBeckyUtils::GetDefaultMailboxDirectory(getter_AddRefs(filterDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ filterDir.forget(aFile);
+ return NS_OK;
+}
+
+nsresult
+nsBeckyFilters::GetFilterFile(bool aIncoming, nsIFile *aLocation, nsIFile **aFile)
+{
+ NS_ENSURE_ARG_POINTER(aLocation);
+ NS_ENSURE_ARG_POINTER(aFile);
+
+ // We assume the caller has already checked that aLocation is a directory,
+ // otherwise it would not make sense to call us.
+
+ nsresult rv;
+ nsCOMPtr<nsIFile> filter;
+ aLocation->Clone(getter_AddRefs(filter));
+ if (aIncoming)
+ rv = filter->Append(NS_LITERAL_STRING("IFilter.def"));
+ else
+ rv = filter->Append(NS_LITERAL_STRING("OFilter.def"));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool exists = false;
+ rv = filter->Exists(&exists);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!exists)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ filter.forget(aFile);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBeckyFilters::AutoLocate(char16_t **aDescription,
+ nsIFile **aLocation,
+ bool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(aLocation);
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ if (aDescription) {
+ *aDescription =
+ nsBeckyStringBundle::GetStringByName(u"BeckyImportDescription");
+ }
+ *aLocation = nullptr;
+ *_retval = false;
+
+ nsresult rv;
+ nsCOMPtr<nsIFile> location;
+ rv = GetDefaultFilterLocation(getter_AddRefs(location));
+ if (NS_FAILED(rv))
+ location = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
+ else
+ *_retval = true;
+
+ location.forget(aLocation);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBeckyFilters::SetLocation(nsIFile *aLocation)
+{
+ NS_ENSURE_ARG_POINTER(aLocation);
+
+ bool exists = false;
+ nsresult rv = aLocation->Exists(&exists);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!exists)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ mLocation = aLocation;
+ return NS_OK;
+}
+
+static nsMsgSearchAttribValue
+ConvertSearchKeyToAttrib(const nsACString &aKey)
+{
+ if (aKey.EqualsLiteral("From") ||
+ aKey.EqualsLiteral("Sender") ||
+ aKey.EqualsLiteral("From, Sender, X-Sender")) {
+ return nsMsgSearchAttrib::Sender;
+ } else if (aKey.EqualsLiteral("Subject")) {
+ return nsMsgSearchAttrib::Subject;
+ } else if (aKey.EqualsLiteral("[body]")) {
+ return nsMsgSearchAttrib::Body;
+ } else if (aKey.EqualsLiteral("Date")) {
+ return nsMsgSearchAttrib::Date;
+ } else if (aKey.EqualsLiteral("To")) {
+ return nsMsgSearchAttrib::To;
+ } else if (aKey.EqualsLiteral("Cc")) {
+ return nsMsgSearchAttrib::CC;
+ } else if (aKey.EqualsLiteral("To, Cc, Bcc:")) {
+ return nsMsgSearchAttrib::ToOrCC;
+ }
+ return -1;
+}
+
+static nsMsgSearchOpValue
+ConvertSearchFlagsToOperator(const nsACString &aFlags)
+{
+ nsCString flags(aFlags);
+ int32_t lastTabPosition = flags.RFindChar('\t');
+ if ((lastTabPosition == -1) ||
+ ((int32_t)aFlags.Length() == lastTabPosition - 1)) {
+ return -1;
+ }
+
+ switch (aFlags.CharAt(0)) {
+ case 'X':
+ return nsMsgSearchOp::DoesntContain;
+ case 'O':
+ if (aFlags.FindChar('T', lastTabPosition + 1) >= 0)
+ return nsMsgSearchOp::BeginsWith;
+ return nsMsgSearchOp::Contains;
+ default:
+ return -1;
+ }
+}
+
+nsresult
+nsBeckyFilters::ParseRuleLine(const nsCString &aLine,
+ nsMsgSearchAttribValue *aSearchAttribute,
+ nsMsgSearchOpValue *aSearchOperator,
+ nsString &aSearchKeyword)
+{
+ int32_t firstColonPosition = aLine.FindChar(':');
+ if (firstColonPosition == -1 ||
+ (int32_t)aLine.Length() == firstColonPosition - 1) {
+ return NS_ERROR_FAILURE;
+ }
+
+ int32_t secondColonPosition = aLine.FindChar(':', firstColonPosition + 1);
+ if (secondColonPosition == -1 ||
+ (int32_t)aLine.Length() == secondColonPosition - 1) {
+ return NS_ERROR_FAILURE;
+ }
+
+ int32_t length = secondColonPosition - firstColonPosition - 1;
+ nsMsgSearchAttribValue searchAttribute;
+ searchAttribute = ConvertSearchKeyToAttrib(Substring(aLine, firstColonPosition + 1, length));
+ if (searchAttribute < 0)
+ return NS_ERROR_FAILURE;
+
+ int32_t tabPosition = aLine.FindChar('\t');
+ if (tabPosition == -1 ||
+ (int32_t)aLine.Length() == tabPosition - 1) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsMsgSearchOpValue searchOperator;
+ searchOperator = ConvertSearchFlagsToOperator(Substring(aLine, tabPosition + 1));
+ if (searchOperator < 0)
+ return NS_ERROR_FAILURE;
+
+ *aSearchOperator = searchOperator;
+ *aSearchAttribute = searchAttribute;
+ length = tabPosition - secondColonPosition - 1;
+ CopyUTF8toUTF16(Substring(aLine, secondColonPosition + 1, length), aSearchKeyword);
+ return NS_OK;
+}
+
+nsresult
+nsBeckyFilters::SetSearchTerm(const nsCString &aLine, nsIMsgFilter *aFilter)
+{
+ NS_ENSURE_ARG_POINTER(aFilter);
+
+ nsresult rv;
+ nsMsgSearchAttribValue searchAttribute = -1;
+ nsMsgSearchOpValue searchOperator = -1;
+ nsAutoString searchKeyword;
+ rv = ParseRuleLine(aLine, &searchAttribute, &searchOperator, searchKeyword);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIMsgSearchTerm> term;
+ rv = aFilter->CreateTerm(getter_AddRefs(term));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = term->SetAttrib(searchAttribute);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = term->SetOp(searchOperator);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIMsgSearchValue> value;
+ rv = term->GetValue(getter_AddRefs(value));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = value->SetAttrib(searchAttribute);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = value->SetStr(searchKeyword);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = term->SetValue(value);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = term->SetBooleanAnd(false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!searchKeyword.IsEmpty())
+ rv = aFilter->SetFilterName(searchKeyword);
+ else
+ rv = aFilter->SetFilterName(NS_LITERAL_STRING("No name"));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return aFilter->AppendTerm(term);
+}
+
+nsresult
+nsBeckyFilters::CreateRuleAction(nsIMsgFilter *aFilter,
+ nsMsgRuleActionType actionType,
+ nsIMsgRuleAction **_retval)
+{
+ nsresult rv;
+ nsCOMPtr<nsIMsgRuleAction> action;
+ rv = aFilter->CreateAction(getter_AddRefs(action));
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = action->SetType(actionType);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ action.forget(_retval);
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckyFilters::GetActionTarget(const nsCString &aLine,
+ nsCString &aTarget)
+{
+ int32_t firstColonPosition = aLine.FindChar(':');
+ if (firstColonPosition < -1 ||
+ aLine.Length() == static_cast<uint32_t>(firstColonPosition)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ aTarget.Assign(Substring(aLine, firstColonPosition + 1));
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckyFilters::GetResendTarget(const nsCString &aLine,
+ nsCString &aTemplate,
+ nsCString &aTargetAddress)
+{
+ nsresult rv;
+ nsAutoCString target;
+ rv = GetActionTarget(aLine, target);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ int32_t asteriskPosition = target.FindChar('*');
+ if (asteriskPosition < 0) {
+ aTemplate.Assign(target);
+ return NS_OK;
+ }
+
+ if (target.Length() == static_cast<uint32_t>(asteriskPosition))
+ return NS_ERROR_FAILURE;
+
+ aTemplate.Assign(StringHead(target, asteriskPosition - 1));
+ aTargetAddress.Assign(Substring(target, asteriskPosition + 1));
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckyFilters::CreateResendAction(const nsCString &aLine,
+ nsIMsgFilter *aFilter,
+ const nsMsgRuleActionType &aActionType,
+ nsIMsgRuleAction **_retval)
+{
+ nsresult rv;
+ nsCOMPtr<nsIMsgRuleAction> action;
+ rv = CreateRuleAction(aFilter, aActionType, getter_AddRefs(action));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoCString templateString;
+ nsAutoCString targetAddress;
+ rv = GetResendTarget(aLine, templateString, targetAddress);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (aActionType == nsMsgFilterAction::Forward)
+ rv = action->SetStrValue(targetAddress);
+ else
+ rv = action->SetStrValue(templateString);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ action.forget(_retval);
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckyFilters::GetFolderNameFromTarget(const nsCString &aTarget, nsAString &aName)
+{
+ int32_t backslashPosition = aTarget.RFindChar('\\');
+ if (backslashPosition > 0) {
+ NS_ConvertUTF8toUTF16 utf16String(Substring(aTarget, backslashPosition + 1));
+ nsBeckyUtils::TranslateFolderName(utf16String, aName);
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckyFilters::GetDistributeTarget(const nsCString &aLine,
+ nsCString &aTargetFolder)
+{
+ nsresult rv;
+ nsAutoCString target;
+ rv = GetActionTarget(aLine, target);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ target.Trim("\\", false, true);
+ nsAutoString folderName;
+ rv = GetFolderNameFromTarget(target, folderName);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr <nsIMsgFolder> folder;
+ rv = GetMessageFolder(folderName, getter_AddRefs(folder));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!folder) {
+ rv = mServer->GetRootMsgFolder(getter_AddRefs(folder));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ return folder->GetURI(aTargetFolder);
+}
+
+nsresult
+nsBeckyFilters::CreateDistributeAction(const nsCString &aLine,
+ nsIMsgFilter *aFilter,
+ const nsMsgRuleActionType &aActionType,
+ nsIMsgRuleAction **_retval)
+{
+ nsresult rv;
+ nsCOMPtr<nsIMsgRuleAction> action;
+ rv = CreateRuleAction(aFilter, aActionType, getter_AddRefs(action));
+ NS_ENSURE_SUCCESS(rv, rv);
+ nsAutoCString targetFolder;
+ rv = GetDistributeTarget(aLine, targetFolder);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = action->SetTargetFolderUri(targetFolder);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ action.forget(_retval);
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckyFilters::CreateLeaveOrDeleteAction(const nsCString &aLine,
+ nsIMsgFilter *aFilter,
+ nsIMsgRuleAction **_retval)
+{
+ nsresult rv;
+ nsMsgRuleActionType actionType;
+ if (aLine.CharAt(3) == '0') {
+ actionType = nsMsgFilterAction::LeaveOnPop3Server;
+ } else if (aLine.CharAt(3) == '1') {
+ if (aLine.CharAt(5) == '1')
+ actionType = nsMsgFilterAction::Delete;
+ else
+ actionType = nsMsgFilterAction::DeleteFromPop3Server;
+ } else {
+ return NS_ERROR_FAILURE;
+ }
+ nsCOMPtr<nsIMsgRuleAction> action;
+ rv = CreateRuleAction(aFilter, actionType, getter_AddRefs(action));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ action.forget(_retval);
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckyFilters::SetRuleAction(const nsCString &aLine, nsIMsgFilter *aFilter)
+{
+ if (!aFilter || aLine.Length() < 4)
+ return NS_ERROR_FAILURE;
+
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsIMsgRuleAction> action;
+ switch (aLine.CharAt(1)) {
+ case 'R': // Reply
+ rv = CreateResendAction(aLine,
+ aFilter,
+ nsMsgFilterAction::Reply,
+ getter_AddRefs(action));
+ break;
+ case 'F': // Forward
+ rv = CreateResendAction(aLine,
+ aFilter,
+ nsMsgFilterAction::Forward,
+ getter_AddRefs(action));
+ break;
+ case 'L': // Leave or delete
+ rv = CreateLeaveOrDeleteAction(aLine, aFilter, getter_AddRefs(action));
+ break;
+ case 'Y': // Copy
+ rv = CreateDistributeAction(aLine,
+ aFilter,
+ nsMsgFilterAction::CopyToFolder,
+ getter_AddRefs(action));
+ break;
+ case 'M': // Move
+ rv = CreateDistributeAction(aLine,
+ aFilter,
+ nsMsgFilterAction::MoveToFolder,
+ getter_AddRefs(action));
+ break;
+ case 'G': // Set flag
+ if (aLine.CharAt(3) == 'R') // Read
+ rv = CreateRuleAction(aFilter, nsMsgFilterAction::MarkRead, getter_AddRefs(action));
+ break;
+ default:
+ return NS_OK;
+ }
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (action) {
+ rv = aFilter->AppendAction(action);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckyFilters::CreateFilter(bool aIncoming, nsIMsgFilter **_retval)
+{
+ NS_ENSURE_STATE(mServer);
+
+ nsCOMPtr <nsIMsgFilterList> filterList;
+ nsresult rv = mServer->GetFilterList(nullptr, getter_AddRefs(filterList));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIMsgFilter> filter;
+ rv = filterList->CreateFilter(EmptyString(), getter_AddRefs(filter));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (aIncoming)
+ filter->SetFilterType(nsMsgFilterType::InboxRule | nsMsgFilterType::Manual);
+ else
+ filter->SetFilterType(nsMsgFilterType::PostOutgoing | nsMsgFilterType::Manual);
+
+ filter->SetEnabled(true);
+ filter.forget(_retval);
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckyFilters::AppendFilter(nsIMsgFilter *aFilter)
+{
+ NS_ENSURE_STATE(mServer);
+
+ nsCOMPtr <nsIMsgFilterList> filterList;
+ nsresult rv = mServer->GetFilterList(nullptr, getter_AddRefs(filterList));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint32_t count;
+ rv = filterList->GetFilterCount(&count);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return filterList->InsertFilterAt(count, aFilter);
+}
+
+nsresult
+nsBeckyFilters::ParseFilterFile(nsIFile *aFile, bool aIncoming)
+{
+ nsresult rv;
+ nsCOMPtr<nsILineInputStream> lineStream;
+ rv = nsBeckyUtils::CreateLineInputStream(aFile, getter_AddRefs(lineStream));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool more = true;
+ nsAutoCString line;
+
+ nsCOMPtr<nsIMsgFilter> filter;
+ while (NS_SUCCEEDED(rv) && more) {
+ rv = lineStream->ReadLine(line, &more);
+
+ switch (line.CharAt(0)) {
+ case ':':
+ if (line.EqualsLiteral(":Begin \"\"")) {
+ CreateFilter(aIncoming, getter_AddRefs(filter));
+ } else if (line.EqualsLiteral(":End \"\"")) {
+ if (filter)
+ AppendFilter(filter);
+ filter = nullptr;
+ }
+ break;
+ case '!':
+ SetRuleAction(line, filter);
+ break;
+ case '@':
+ SetSearchTerm(line, filter);
+ break;
+ case '$': // $X: disabled
+ if (StringBeginsWith(line, NS_LITERAL_CSTRING("$X")) && filter) {
+ filter->SetEnabled(false);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBeckyFilters::Import(char16_t **aError,
+ bool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(aError);
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ // If mLocation is null, set it to the default filter directory.
+ // If mLocation is a file, we import it as incoming folder.
+ // If mLocation is a directory, we try to import incoming and outgoing folders
+ // from it (in default files).
+
+ *_retval = false;
+ nsresult rv;
+ nsCOMPtr<nsIFile> filterFile;
+
+ bool haveFile = false;
+
+ if (!mLocation) {
+ bool retval = false;
+ rv = AutoLocate(nullptr, getter_AddRefs(mLocation), &retval);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!retval)
+ return NS_ERROR_FILE_NOT_FOUND;
+ }
+
+ // What type of location do we have?
+ bool isDirectory = false;
+ rv = mLocation->IsDirectory(&isDirectory);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (isDirectory) {
+ haveFile = false;
+ } else {
+ bool isFile = false;
+ rv = mLocation->IsFile(&isFile);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (isFile) {
+ haveFile = true;
+ mLocation->Clone(getter_AddRefs(filterFile));
+ } else {
+ // mLocation is neither file nor directory.
+ return NS_ERROR_UNEXPECTED;
+ }
+ }
+
+ bool haveIncoming = true;
+ if (haveFile) {
+ // If the passed filename equals OFilter.def, import as outgoing filters.
+ // Everything else is considered incoming.
+ nsAutoString fileName;
+ rv = mLocation->GetLeafName(fileName);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (fileName.EqualsLiteral("OFilter.def"))
+ haveIncoming = false;
+ }
+
+ // Try importing from the passed in file or the default incoming filters file.
+ if ((haveFile && haveIncoming) || (!haveFile &&
+ NS_SUCCEEDED(GetFilterFile(true, mLocation, getter_AddRefs(filterFile)))))
+ {
+ rv = CollectServers();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = nsBeckyUtils::ConvertToUTF8File(filterFile, getter_AddRefs(mConvertedFile));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = ParseFilterFile(mConvertedFile, true);
+ if (NS_SUCCEEDED(rv))
+ *_retval = true;
+
+ (void)RemoveConvertedFile();
+ }
+
+ // If we didn't have a file passed (but a directory), try finding also outgoing filters.
+ if ((haveFile && !haveIncoming) || (!haveFile &&
+ NS_SUCCEEDED(GetFilterFile(false, mLocation, getter_AddRefs(filterFile)))))
+ {
+ rv = CollectServers();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = nsBeckyUtils::ConvertToUTF8File(filterFile, getter_AddRefs(mConvertedFile));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = ParseFilterFile(mConvertedFile, false);
+ if (NS_SUCCEEDED(rv))
+ *_retval = true;
+
+ (void)RemoveConvertedFile();
+ }
+
+ return rv;
+}
+
+nsresult
+nsBeckyFilters::FindMessageFolder(const nsAString &aName,
+ nsIMsgFolder *aParentFolder,
+ nsIMsgFolder **_retval)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIMsgFolder> found;
+ rv = aParentFolder->GetChildNamed(aName, getter_AddRefs(found));
+ if (found) {
+ found.forget(_retval);
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsISimpleEnumerator> children;
+ rv = aParentFolder->GetSubFolders(getter_AddRefs(children));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool more;
+ nsCOMPtr<nsISupports> entry;
+ while (NS_SUCCEEDED(children->HasMoreElements(&more)) && more) {
+ rv = children->GetNext(getter_AddRefs(entry));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIMsgFolder> child = do_QueryInterface(entry, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = FindMessageFolder(aName, child, getter_AddRefs(found));
+ if (found) {
+ found.forget(_retval);
+ return NS_OK;
+ }
+ }
+
+ return NS_MSG_ERROR_INVALID_FOLDER_NAME;
+}
+
+nsresult
+nsBeckyFilters::FindMessageFolderInServer(const nsAString &aName,
+ nsIMsgIncomingServer *aServer,
+ nsIMsgFolder **_retval)
+{
+ nsresult rv;
+ nsCOMPtr <nsIMsgFolder> rootFolder;
+ rv = aServer->GetRootMsgFolder(getter_AddRefs(rootFolder));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return FindMessageFolder(aName, rootFolder, _retval);
+}
+
+nsresult
+nsBeckyFilters::GetMessageFolder(const nsAString &aName,
+ nsIMsgFolder **_retval)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIMsgAccountManager> accountManager;
+ accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIArray> accounts;
+ rv = accountManager->GetAccounts(getter_AddRefs(accounts));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint32_t accountCount;
+ rv = accounts->GetLength(&accountCount);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIMsgFolder> found;
+ for (uint32_t i = 0; i < accountCount; i++) {
+ nsCOMPtr<nsIMsgAccount> account(do_QueryElementAt(accounts, i));
+ if (!account)
+ continue;
+
+ nsCOMPtr<nsIMsgIncomingServer> server;
+ account->GetIncomingServer(getter_AddRefs(server));
+ if (!server)
+ continue;
+ FindMessageFolderInServer(aName, server, getter_AddRefs(found));
+ if (found)
+ break;
+ }
+
+ if (!found) {
+ nsCOMPtr<nsIMsgIncomingServer> server;
+ rv = accountManager->GetLocalFoldersServer(getter_AddRefs(server));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ FindMessageFolderInServer(aName, server, getter_AddRefs(found));
+ }
+
+ if (!found)
+ return NS_MSG_ERROR_INVALID_FOLDER_NAME;
+
+ found.forget(_retval);
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckyFilters::CollectServers()
+{
+ nsresult rv;
+ nsCOMPtr<nsIMsgAccountManager> accountManager;
+ accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIMsgAccount> defaultAccount;
+ rv = accountManager->GetDefaultAccount(getter_AddRefs(defaultAccount));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIMsgIncomingServer> server;
+ return defaultAccount->GetIncomingServer(getter_AddRefs(mServer));
+}
+
+nsresult
+nsBeckyFilters::RemoveConvertedFile()
+{
+ nsresult rv = NS_OK;
+ if (mConvertedFile) {
+ bool exists = false;
+ mConvertedFile->Exists(&exists);
+ if (exists) {
+ rv = mConvertedFile->Remove(false);
+ if (NS_SUCCEEDED(rv))
+ mConvertedFile = nullptr;
+ }
+ }
+ return rv;
+}
+
diff --git a/mailnews/import/becky/src/nsBeckyFilters.h b/mailnews/import/becky/src/nsBeckyFilters.h
new file mode 100644
index 000000000..20dd6d5ee
--- /dev/null
+++ b/mailnews/import/becky/src/nsBeckyFilters.h
@@ -0,0 +1,77 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 nsBeckyFilters_h___
+#define nsBeckyFilters_h___
+
+#include "nsIImportFilters.h"
+#include "nsIFile.h"
+#include "nsIMsgIncomingServer.h"
+#include "nsMsgFilterCore.h"
+
+class nsIMsgFilter;
+class nsIMsgRuleAction;
+class nsCString;
+
+class nsBeckyFilters final : public nsIImportFilters
+{
+public:
+ nsBeckyFilters();
+ static nsresult Create(nsIImportFilters **aImport);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIIMPORTFILTERS
+
+private:
+ virtual ~nsBeckyFilters();
+
+ nsCOMPtr<nsIFile> mLocation;
+ nsCOMPtr<nsIMsgIncomingServer> mServer;
+ nsCOMPtr<nsIFile> mConvertedFile;
+
+ nsresult GetDefaultFilterLocation(nsIFile **aFile);
+ nsresult GetFilterFile(bool aIncoming, nsIFile *aLocation, nsIFile **aFile);
+ nsresult ParseFilterFile(nsIFile *aFile, bool aIncoming);
+ nsresult ParseRuleLine(const nsCString &aLine,
+ nsMsgSearchAttribValue *aSearchAttribute,
+ nsMsgSearchOpValue *aSearchOperator,
+ nsString &aSearchKeyword);
+ nsresult CollectServers();
+ nsresult FindMessageFolder(const nsAString& aName,
+ nsIMsgFolder *aParantFolder,
+ nsIMsgFolder **_retval);
+ nsresult FindMessageFolderInServer(const nsAString& aName,
+ nsIMsgIncomingServer *aServer,
+ nsIMsgFolder **_retval);
+ nsresult GetMessageFolder(const nsAString& aName, nsIMsgFolder **_retval);
+ nsresult GetActionTarget(const nsCString &aLine, nsCString &aTarget);
+ nsresult GetFolderNameFromTarget(const nsCString &aTarget, nsAString &aName);
+ nsresult GetDistributeTarget(const nsCString &aLine,
+ nsCString &aTargetFolder);
+ nsresult GetResendTarget(const nsCString &aLine,
+ nsCString &aTemplate,
+ nsCString &aTargetAddress);
+ nsresult CreateRuleAction(nsIMsgFilter *aFilter,
+ nsMsgRuleActionType actionType,
+ nsIMsgRuleAction **_retval);
+ nsresult CreateDistributeAction(const nsCString &aLine,
+ nsIMsgFilter *aFilter,
+ const nsMsgRuleActionType &aActionType,
+ nsIMsgRuleAction **_retval);
+ nsresult CreateLeaveOrDeleteAction(const nsCString &aLine,
+ nsIMsgFilter *aFilter,
+ nsIMsgRuleAction **_retval);
+ nsresult CreateResendAction(const nsCString &aLine,
+ nsIMsgFilter *aFilter,
+ const nsMsgRuleActionType &aActionType,
+ nsIMsgRuleAction **_retval);
+ nsresult CreateFilter(bool aIncoming, nsIMsgFilter **_retval);
+ nsresult AppendFilter(nsIMsgFilter *aFilter);
+ nsresult SetRuleAction(const nsCString &aLine, nsIMsgFilter *aFilter);
+ nsresult SetSearchTerm(const nsCString &aLine, nsIMsgFilter *aFilter);
+ nsresult RemoveConvertedFile();
+};
+
+#endif /* nsBeckyFilters_h___ */
diff --git a/mailnews/import/becky/src/nsBeckyImport.cpp b/mailnews/import/becky/src/nsBeckyImport.cpp
new file mode 100644
index 000000000..d4820528a
--- /dev/null
+++ b/mailnews/import/becky/src/nsBeckyImport.cpp
@@ -0,0 +1,168 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 "nscore.h"
+#include "nsIServiceManager.h"
+#include "nsIImportService.h"
+#include "nsIComponentManager.h"
+#include "nsIMemory.h"
+#include "nsIImportMail.h"
+#include "nsIImportMailboxDescriptor.h"
+#include "nsIImportGeneric.h"
+#include "nsIImportAddressBooks.h"
+#include "nsIImportABDescriptor.h"
+#include "nsIImportSettings.h"
+#include "nsIImportFilters.h"
+#include "nsIImportFieldMap.h"
+#include "nsXPCOM.h"
+#include "nsISupportsPrimitives.h"
+#include "nsIOutputStream.h"
+#include "nsIAddrDatabase.h"
+#include "nsTextFormatter.h"
+#include "nsIStringBundle.h"
+#include "nsUnicharUtils.h"
+#include "nsIMsgTagService.h"
+#include "nsMsgBaseCID.h"
+#include "nsCOMPtr.h"
+#include "nsServiceManagerUtils.h"
+#include "nsComponentManagerUtils.h"
+
+#include "nsBeckyImport.h"
+#include "nsBeckyMail.h"
+#include "nsBeckyAddressBooks.h"
+#include "nsBeckySettings.h"
+#include "nsBeckyFilters.h"
+#include "nsBeckyStringBundle.h"
+
+nsBeckyImport::nsBeckyImport()
+{
+}
+
+nsBeckyImport::~nsBeckyImport()
+{
+}
+
+NS_IMPL_ISUPPORTS(nsBeckyImport, nsIImportModule)
+
+NS_IMETHODIMP
+nsBeckyImport::GetName(char16_t **aName)
+{
+ NS_ENSURE_ARG_POINTER(aName);
+ *aName =
+ nsBeckyStringBundle::GetStringByName(u"BeckyImportName");
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBeckyImport::GetDescription(char16_t **aDescription)
+{
+ NS_ENSURE_ARG_POINTER(aDescription);
+ *aDescription =
+ nsBeckyStringBundle::GetStringByName(u"BeckyImportDescription");
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBeckyImport::GetSupports(char **aSupports)
+{
+ NS_ENSURE_ARG_POINTER(aSupports);
+ *aSupports = strdup(kBeckySupportsString);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBeckyImport::GetSupportsUpgrade(bool *aUpgrade)
+{
+ NS_ENSURE_ARG_POINTER(aUpgrade);
+ *aUpgrade = true;
+ return NS_OK;
+}
+
+nsresult
+nsBeckyImport::GetMailImportInterface(nsISupports **aInterface)
+{
+ nsCOMPtr<nsIImportMail> importer;
+ nsresult rv = nsBeckyMail::Create(getter_AddRefs(importer));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIImportService> importService(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsIImportGeneric> generic;
+ rv = importService->CreateNewGenericMail(getter_AddRefs(generic));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ generic->SetData("mailInterface", importer);
+
+ nsString name;
+ name.Adopt(nsBeckyStringBundle::GetStringByName(u"BeckyImportName"));
+
+ nsCOMPtr<nsISupportsString> nameString(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nameString->SetData(name);
+ generic->SetData("name", nameString);
+
+ return CallQueryInterface(generic, aInterface);
+}
+
+nsresult
+nsBeckyImport::GetAddressBookImportInterface(nsISupports **aInterface)
+{
+ nsresult rv;
+ nsCOMPtr<nsIImportAddressBooks> importer;
+ rv = nsBeckyAddressBooks::Create(getter_AddRefs(importer));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIImportService> importService(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIImportGeneric> generic;
+ rv = importService->CreateNewGenericAddressBooks(getter_AddRefs(generic));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ generic->SetData("addressInterface", importer);
+ return CallQueryInterface(generic, aInterface);
+}
+
+nsresult
+nsBeckyImport::GetSettingsImportInterface(nsISupports **aInterface)
+{
+ nsresult rv;
+ nsCOMPtr<nsIImportSettings> importer;
+ rv = nsBeckySettings::Create(getter_AddRefs(importer));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return CallQueryInterface(importer, aInterface);
+}
+
+nsresult
+nsBeckyImport::GetFiltersImportInterface(nsISupports **aInterface)
+{
+ nsresult rv;
+ nsCOMPtr<nsIImportFilters> importer;
+ rv = nsBeckyFilters::Create(getter_AddRefs(importer));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return CallQueryInterface(importer, aInterface);
+}
+
+NS_IMETHODIMP
+nsBeckyImport::GetImportInterface(const char *aImportType, nsISupports **aInterface)
+{
+ NS_ENSURE_ARG_POINTER(aImportType);
+ NS_ENSURE_ARG_POINTER(aInterface);
+
+ *aInterface = nullptr;
+ if (!strcmp(aImportType, "mail"))
+ return GetMailImportInterface(aInterface);
+ if (!strcmp(aImportType, "addressbook"))
+ return GetAddressBookImportInterface(aInterface);
+ if (!strcmp(aImportType, "settings"))
+ return GetSettingsImportInterface(aInterface);
+ if (!strcmp(aImportType, "filters"))
+ return GetFiltersImportInterface(aInterface);
+
+ return NS_ERROR_NOT_AVAILABLE;
+}
diff --git a/mailnews/import/becky/src/nsBeckyImport.h b/mailnews/import/becky/src/nsBeckyImport.h
new file mode 100644
index 000000000..60d81c18c
--- /dev/null
+++ b/mailnews/import/becky/src/nsBeckyImport.h
@@ -0,0 +1,36 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 nsBeckyImport_h___
+#define nsBeckyImport_h___
+
+#include "nsIImportModule.h"
+
+#define NS_BECKYIMPORT_CID \
+{ \
+ 0x7952a6cf, 0x2442,0x4c04, \
+ {0x9f, 0x02, 0x15, 0x0b, 0x15, 0xa0, 0xa8, 0x41}}
+
+#define kBeckySupportsString NS_IMPORT_MAIL_STR "," NS_IMPORT_ADDRESS_STR "," NS_IMPORT_SETTINGS_STR "," NS_IMPORT_FILTERS_STR
+
+class nsBeckyImport final : public nsIImportModule
+{
+public:
+ nsBeckyImport();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIIMPORTMODULE
+
+private:
+ virtual ~nsBeckyImport();
+
+ nsresult GetMailImportInterface(nsISupports **aInterface);
+ nsresult GetAddressBookImportInterface(nsISupports **aInterface);
+ nsresult GetSettingsImportInterface(nsISupports **aInterface);
+ nsresult GetFiltersImportInterface(nsISupports **aInterface);
+
+};
+
+#endif /* nsBeckyImport_h___ */
diff --git a/mailnews/import/becky/src/nsBeckyMail.cpp b/mailnews/import/becky/src/nsBeckyMail.cpp
new file mode 100644
index 000000000..9c837d190
--- /dev/null
+++ b/mailnews/import/becky/src/nsBeckyMail.cpp
@@ -0,0 +1,641 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 "nsString.h"
+#include "nsCOMPtr.h"
+#include "nsIFile.h"
+#include "nsIInputStream.h"
+#include "nsIOutputStream.h"
+#include "nsILineInputStream.h"
+#include "nsNetUtil.h"
+#include "nsIArray.h"
+#include "nsIImportService.h"
+#include "nsIImportMailboxDescriptor.h"
+#include "nsIMsgHdr.h"
+#include "nsIMsgFolder.h"
+#include "nsIMsgPluggableStore.h"
+#include "nsIMutableArray.h"
+#include "nsMsgUtils.h"
+#include "nsMsgLocalFolderHdrs.h"
+#include "nsMsgMessageFlags.h"
+#include "nsTArray.h"
+#include "nspr.h"
+#include "nsIStringBundle.h"
+#include "nsThreadUtils.h"
+
+#include "nsBeckyMail.h"
+#include "nsBeckyUtils.h"
+#include "nsBeckyStringBundle.h"
+
+#define FROM_LINE "From - Mon Jan 1 00:00:00 1965" MSG_LINEBREAK
+#define X_BECKY_STATUS_HEADER "X-Becky-Status"
+#define X_BECKY_INCLUDE_HEADER "X-Becky-Include"
+
+enum {
+ BECKY_STATUS_READ = 1 << 0,
+ BECKY_STATUS_FORWARDED = 1 << 1,
+ BECKY_STATUS_REPLIED = 1 << 2
+};
+
+NS_IMPL_ISUPPORTS(nsBeckyMail, nsIImportMail)
+
+nsresult
+nsBeckyMail::Create(nsIImportMail **aImport)
+{
+ NS_ENSURE_ARG_POINTER(aImport);
+
+ *aImport = new nsBeckyMail();
+
+ NS_ADDREF(*aImport);
+ return NS_OK;
+}
+
+nsBeckyMail::nsBeckyMail()
+: mReadBytes(0)
+{
+}
+
+nsBeckyMail::~nsBeckyMail()
+{
+}
+
+NS_IMETHODIMP
+nsBeckyMail::GetDefaultLocation(nsIFile **aLocation,
+ bool *aFound,
+ bool *aUserVerify)
+{
+ NS_ENSURE_ARG_POINTER(aFound);
+ NS_ENSURE_ARG_POINTER(aLocation);
+ NS_ENSURE_ARG_POINTER(aUserVerify);
+
+ *aLocation = nullptr;
+ *aUserVerify = true;
+ *aFound = false;
+ if (NS_SUCCEEDED(nsBeckyUtils::GetDefaultMailboxDirectory(aLocation)))
+ *aFound = true;
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckyMail::CreateMailboxDescriptor(nsIImportMailboxDescriptor **aDescriptor)
+{
+ nsresult rv;
+ nsCOMPtr<nsIImportService> importService;
+ importService = do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return importService->CreateNewMailboxDescriptor(aDescriptor);
+}
+
+nsresult
+nsBeckyMail::GetMailboxName(nsIFile *aMailbox, nsAString &aName)
+{
+ nsCOMPtr<nsIFile> iniFile;
+ nsBeckyUtils::GetMailboxINIFile(aMailbox, getter_AddRefs(iniFile));
+ if (iniFile) {
+ nsCOMPtr<nsIFile> convertedFile;
+ nsBeckyUtils::ConvertToUTF8File(iniFile, getter_AddRefs(convertedFile));
+ if (convertedFile) {
+ nsAutoCString utf8Name;
+ nsBeckyUtils::GetMailboxNameFromINIFile(convertedFile, utf8Name);
+ convertedFile->Remove(false);
+ CopyUTF8toUTF16(utf8Name, aName);
+ }
+ }
+
+ if (aName.IsEmpty()) {
+ nsAutoString name;
+ aMailbox->GetLeafName(name);
+ name.Trim("!", true, false);
+ aName.Assign(name);
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckyMail::AppendMailboxDescriptor(nsIFile *aEntry,
+ const nsString &aName,
+ uint32_t aDepth,
+ nsIMutableArray *aCollected)
+{
+ nsresult rv;
+ nsCOMPtr<nsIImportMailboxDescriptor> descriptor;
+ rv = CreateMailboxDescriptor(getter_AddRefs(descriptor));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ int64_t size;
+ rv = aEntry->GetFileSize(&size);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = descriptor->SetSize(size);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = descriptor->SetDisplayName(aName.get());
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIFile> mailboxFile;
+ rv = descriptor->GetFile(getter_AddRefs(mailboxFile));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ descriptor->SetDepth(aDepth);
+
+ mailboxFile->InitWithFile(aEntry);
+ aCollected->AppendElement(descriptor, false);
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckyMail::CollectMailboxesInFolderListFile(nsIFile *aListFile,
+ uint32_t aDepth,
+ nsIMutableArray *aCollected)
+{
+ nsresult rv;
+ nsCOMPtr<nsILineInputStream> lineStream;
+ rv = nsBeckyUtils::CreateLineInputStream(aListFile,
+ getter_AddRefs(lineStream));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIFile> parent;
+ rv = aListFile->GetParent(getter_AddRefs(parent));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool more = true;
+ nsAutoCString folderName;
+ bool isEmpty = true;
+ while (more && NS_SUCCEEDED(rv)) {
+ rv = lineStream->ReadLine(folderName, &more);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (folderName.IsEmpty())
+ continue;
+
+ nsCOMPtr<nsIFile> folder;
+ rv = parent->Clone(getter_AddRefs(folder));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = folder->AppendNative(folderName);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ isEmpty = false;
+ rv = CollectMailboxesInDirectory(folder, aDepth + 1, aCollected);
+ }
+
+ return isEmpty ? NS_ERROR_FILE_NOT_FOUND : NS_OK;
+}
+
+nsresult
+nsBeckyMail::CollectMailboxesInDirectory(nsIFile *aDirectory,
+ uint32_t aDepth,
+ nsIMutableArray *aCollected)
+{
+ nsAutoString mailboxName;
+ nsresult rv = GetMailboxName(aDirectory, mailboxName);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (aDepth != 0)
+ AppendMailboxDescriptor(aDirectory, mailboxName, aDepth, aCollected);
+
+ nsCOMPtr<nsIFile> folderListFile;
+ rv = nsBeckyUtils::GetFolderListFile(aDirectory, getter_AddRefs(folderListFile));
+ bool folderListExists = false;
+
+ if (NS_SUCCEEDED(rv)) {
+ rv = CollectMailboxesInFolderListFile(folderListFile, aDepth, aCollected);
+ folderListExists = true;
+ }
+
+ nsCOMPtr<nsISimpleEnumerator> entries;
+ rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool more;
+ while (NS_SUCCEEDED(entries->HasMoreElements(&more)) && more) {
+ nsCOMPtr<nsISupports> entry;
+ rv = entries->GetNext(getter_AddRefs(entry));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIFile> file = do_QueryInterface(entry, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoString name;
+ rv = file->GetLeafName(name);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (StringEndsWith(name, NS_LITERAL_STRING(".bmf"))) {
+ AppendMailboxDescriptor(file, mailboxName, aDepth, aCollected);
+ }
+
+ // The Folder.lst file is not created if there is only one sub folder,
+ // so we need to find the sub folder by our hands.
+ // The folder name does not begin with # or ! maybe. Yes, maybe...
+ if (!folderListExists) {
+ if (StringBeginsWith(name, NS_LITERAL_STRING("#")) ||
+ StringBeginsWith(name, NS_LITERAL_STRING("!")))
+ continue;
+
+ bool isDirectory = false;
+ rv = file->IsDirectory(&isDirectory);
+ if (isDirectory) {
+ CollectMailboxesInDirectory(file, aDepth + 1, aCollected);
+ continue;
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBeckyMail::FindMailboxes(nsIFile *aLocation, nsIArray **_retval)
+{
+ NS_ENSURE_ARG_POINTER(aLocation);
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ nsresult rv;
+ nsCOMPtr<nsIMutableArray> array(do_CreateInstance(NS_ARRAY_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = CollectMailboxesInDirectory(aLocation, 0, array);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ array.forget(_retval);
+
+ return NS_OK;
+}
+
+static nsresult
+GetBeckyStatusValue(const nsCString &aHeader, nsACString &aValue)
+{
+ int32_t valueStartPosition;
+
+ valueStartPosition = aHeader.FindChar(':');
+ if (valueStartPosition < 0)
+ return NS_ERROR_UNEXPECTED;
+
+ valueStartPosition++;
+
+ int32_t commaPosition = aHeader.FindChar(',', valueStartPosition);
+ if (commaPosition < 0)
+ return NS_ERROR_UNEXPECTED;
+
+ nsAutoCString value(Substring(aHeader,
+ valueStartPosition,
+ commaPosition - valueStartPosition));
+ value.Trim(" \t");
+
+ aValue.Assign(value);
+
+ return NS_OK;
+}
+
+static nsresult
+GetBeckyIncludeValue(const nsCString &aHeader, nsACString &aValue)
+{
+ int32_t valueStartPosition;
+
+ valueStartPosition = aHeader.FindChar(':');
+ if (valueStartPosition < 0)
+ return NS_ERROR_FAILURE;
+
+ valueStartPosition++;
+ nsAutoCString value(Substring(aHeader, valueStartPosition));
+ value.Trim(" \t");
+
+ aValue.Assign(value);
+
+ return NS_OK;
+}
+
+static bool
+ConvertBeckyStatusToMozillaStatus(const nsCString &aHeader,
+ nsMsgMessageFlagType *aMozillaStatusFlag)
+{
+ nsresult rv;
+ nsAutoCString statusString;
+ rv = GetBeckyStatusValue(aHeader, statusString);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ nsresult errorCode;
+ uint32_t beckyStatusFlag = static_cast<uint32_t>(statusString.ToInteger(&errorCode, 16));
+ if (NS_FAILED(errorCode))
+ return false;
+
+ if (beckyStatusFlag & BECKY_STATUS_READ)
+ *aMozillaStatusFlag |= nsMsgMessageFlags::Read;
+ if (beckyStatusFlag & BECKY_STATUS_FORWARDED)
+ *aMozillaStatusFlag |= nsMsgMessageFlags::Forwarded;
+ if (beckyStatusFlag & BECKY_STATUS_REPLIED)
+ *aMozillaStatusFlag |= nsMsgMessageFlags::Replied;
+
+ return true;
+}
+
+static inline bool
+CheckHeaderKey(const nsCString &aHeader, const char *aKeyString)
+{
+ nsAutoCString key(StringHead(aHeader, aHeader.FindChar(':')));
+ key.Trim(" \t");
+ return key.Equals(aKeyString);
+}
+
+static inline bool
+IsBeckyStatusHeader(const nsCString &aHeader)
+{
+ return CheckHeaderKey(aHeader, X_BECKY_STATUS_HEADER);
+}
+
+static inline bool
+IsBeckyIncludeLine(const nsCString &aLine)
+{
+ return CheckHeaderKey(aLine, X_BECKY_INCLUDE_HEADER);
+}
+
+static inline bool
+IsEndOfHeaders(const nsCString &aLine)
+{
+ return aLine.IsEmpty();
+}
+
+static inline bool
+IsEndOfMessage(const nsCString &aLine)
+{
+ return aLine.Equals(".");
+}
+
+class ImportMessageRunnable: public mozilla::Runnable
+{
+public:
+ ImportMessageRunnable(nsIFile *aMessageFile,
+ nsIMsgFolder *aFolder);
+ NS_DECL_NSIRUNNABLE
+private:
+ nsresult WriteHeaders(nsCString &aHeaders, nsIOutputStream *aOutputStream);
+ nsresult HandleHeaderLine(const nsCString &aHeaderLine, nsACString &aHeaders);
+ nsresult GetAttachmentFile(nsIFile *aMailboxFile,
+ const nsCString &aHeader,
+ nsIFile **_retval);
+ nsresult WriteAttachmentFile(nsIFile *aMailboxFile,
+ const nsCString &aHeader,
+ nsIOutputStream *aOutputStream);
+
+ nsCOMPtr<nsIFile> mMessageFile;
+ nsCOMPtr<nsIMsgFolder> mFolder;
+};
+
+ImportMessageRunnable::ImportMessageRunnable(nsIFile *aMessageFile,
+ nsIMsgFolder *aFolder) :
+ mMessageFile(aMessageFile), mFolder(aFolder)
+{
+}
+
+nsresult
+ImportMessageRunnable::WriteHeaders(nsCString &aHeaders,
+ nsIOutputStream *aOutputStream)
+{
+ nsresult rv;
+ uint32_t writtenBytes = 0;
+
+ rv = aOutputStream->Write(FROM_LINE, strlen(FROM_LINE), &writtenBytes);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = aOutputStream->Write(aHeaders.get(), aHeaders.Length(), &writtenBytes);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = aOutputStream->Write(MSG_LINEBREAK, strlen(MSG_LINEBREAK), &writtenBytes);
+ NS_ENSURE_SUCCESS(rv, rv);
+ aHeaders.Truncate();
+
+ return NS_OK;
+}
+
+nsresult
+ImportMessageRunnable::HandleHeaderLine(const nsCString &aHeaderLine,
+ nsACString &aHeaders)
+{
+ aHeaders.Append(aHeaderLine);
+ aHeaders.AppendLiteral(MSG_LINEBREAK);
+
+ nsMsgMessageFlagType flag = 0;
+ if (IsBeckyStatusHeader(aHeaderLine) &&
+ ConvertBeckyStatusToMozillaStatus(aHeaderLine, &flag)) {
+ char *statusLine;
+ statusLine = PR_smprintf(X_MOZILLA_STATUS_FORMAT MSG_LINEBREAK, flag);
+ aHeaders.Append(statusLine);
+ PR_smprintf_free(statusLine);
+ aHeaders.AppendLiteral(X_MOZILLA_KEYWORDS);
+ }
+
+ return NS_OK;
+}
+
+nsresult
+ImportMessageRunnable::GetAttachmentFile(nsIFile *aMailboxFile,
+ const nsCString &aHeader,
+ nsIFile **_retval)
+{
+ nsresult rv;
+ nsCOMPtr<nsIFile> attachmentFile;
+
+ rv = aMailboxFile->Clone(getter_AddRefs(attachmentFile));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = attachmentFile->Append(NS_LITERAL_STRING("#Attach"));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoCString nativeAttachmentPath;
+ rv = GetBeckyIncludeValue(aHeader, nativeAttachmentPath);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = attachmentFile->AppendRelativeNativePath(nativeAttachmentPath);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool exists = false;
+ attachmentFile->Exists(&exists);
+ if (!exists)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ attachmentFile.forget(_retval);
+ return NS_OK;
+}
+
+nsresult
+ImportMessageRunnable::WriteAttachmentFile(nsIFile *aMailboxFile,
+ const nsCString &aHeader,
+ nsIOutputStream *aOutputStream)
+{
+ nsresult rv;
+ nsCOMPtr<nsIFile> parentDirectory;
+ rv = aMailboxFile->GetParent(getter_AddRefs(parentDirectory));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIFile> attachmentFile;
+ rv = GetAttachmentFile(parentDirectory,
+ aHeader,
+ getter_AddRefs(attachmentFile));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIInputStream> inputStream;
+ rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream),
+ attachmentFile);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ char buffer[FILE_IO_BUFFER_SIZE];
+ uint32_t readBytes = 0;
+ uint32_t writtenBytes = 0;
+ rv = aOutputStream->Write(MSG_LINEBREAK, strlen(MSG_LINEBREAK), &writtenBytes);
+ while (NS_SUCCEEDED(inputStream->Read(buffer, sizeof(buffer), &readBytes)) &&
+ readBytes > 0) {
+ rv = aOutputStream->Write(buffer, readBytes, &writtenBytes);
+ if (NS_FAILED(rv))
+ break;
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP ImportMessageRunnable::Run()
+{
+ nsCOMPtr<nsIMsgPluggableStore> msgStore;
+ nsresult rv = mFolder->GetMsgStore(getter_AddRefs(msgStore));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsILineInputStream> lineStream;
+ rv = nsBeckyUtils::CreateLineInputStream(mMessageFile,
+ getter_AddRefs(lineStream));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool reusable;
+ nsCOMPtr<nsIMsgDBHdr> msgHdr;
+ nsCOMPtr<nsIOutputStream> outputStream;
+ rv = msgStore->GetNewMsgOutputStream(mFolder, getter_AddRefs(msgHdr), &reusable,
+ getter_AddRefs(outputStream));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool inHeader = true;
+ bool more = true;
+ nsAutoCString headers;
+ while (NS_SUCCEEDED(rv) && more) {
+ nsAutoCString line;
+ rv = lineStream->ReadLine(line, &more);
+ if (NS_FAILED(rv))
+ break;
+
+ if (inHeader) {
+ if (IsEndOfHeaders(line)) {
+ inHeader = false;
+ rv = WriteHeaders(headers, outputStream);
+ } else {
+ rv = HandleHeaderLine(line, headers);
+ }
+ } else if (IsEndOfMessage(line)) {
+ inHeader = true;
+ rv = msgStore->FinishNewMessage(outputStream, msgHdr);
+ if (!reusable)
+ outputStream->Close();
+ rv = msgStore->GetNewMsgOutputStream(mFolder, getter_AddRefs(msgHdr), &reusable,
+ getter_AddRefs(outputStream));
+ } else if (IsBeckyIncludeLine(line)) {
+ rv = WriteAttachmentFile(mMessageFile, line, outputStream);
+ } else {
+ uint32_t writtenBytes = 0;
+ if (StringBeginsWith(line, NS_LITERAL_CSTRING("..")))
+ line.Cut(0, 1);
+ else if (CheckHeaderKey(line, "From"))
+ line.Insert('>', 0);
+
+ line.AppendLiteral(MSG_LINEBREAK);
+ rv = outputStream->Write(line.get(), line.Length(), &writtenBytes);
+ }
+ }
+
+ if (outputStream) {
+ if (NS_FAILED(rv))
+ msgStore->DiscardNewMessage(outputStream, msgHdr);
+ outputStream->Close();
+ }
+
+ return rv;
+}
+
+static
+nsresult ProxyImportMessage(nsIFile *aMessageFile,
+ nsIMsgFolder *aFolder)
+{
+ RefPtr<ImportMessageRunnable> importMessage =
+ new ImportMessageRunnable(aMessageFile, aFolder);
+ return NS_DispatchToMainThread(importMessage, NS_DISPATCH_SYNC);
+}
+
+nsresult
+nsBeckyMail::ImportMailFile(nsIFile *aMailFile,
+ nsIMsgFolder *aDestination)
+{
+ int64_t size;
+ aMailFile->GetFileSize(&size);
+ if (size == 0)
+ return NS_OK;
+
+ return ProxyImportMessage(aMailFile, aDestination);
+}
+
+NS_IMETHODIMP
+nsBeckyMail::ImportMailbox(nsIImportMailboxDescriptor *aSource,
+ nsIMsgFolder *aDestination,
+ char16_t **aErrorLog,
+ char16_t **aSuccessLog,
+ bool *aFatalError)
+{
+ NS_ENSURE_ARG_POINTER(aSource);
+ NS_ENSURE_ARG_POINTER(aDestination);
+ NS_ENSURE_ARG_POINTER(aErrorLog);
+ NS_ENSURE_ARG_POINTER(aSuccessLog);
+ NS_ENSURE_ARG_POINTER(aFatalError);
+
+ mReadBytes = 0;
+
+ nsresult rv;
+ nsCOMPtr<nsIFile> mailboxFolder;
+ rv = aSource->GetFile(getter_AddRefs(mailboxFolder));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = ImportMailFile(mailboxFolder, aDestination);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint32_t finalSize;
+ aSource->GetSize(&finalSize);
+ mReadBytes = finalSize;
+
+ nsAutoString name;
+ aSource->GetDisplayName(getter_Copies(name));
+
+ nsAutoString successMessage;
+ const char16_t *format = { name.get() };
+ rv =
+ nsBeckyStringBundle::FormatStringFromName(u"BeckyImportMailboxSuccess",
+ &format,
+ 1,
+ getter_Copies(successMessage));
+ successMessage.AppendLiteral("\n");
+ *aSuccessLog = ToNewUnicode(successMessage);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsBeckyMail::GetImportProgress(uint32_t *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = mReadBytes;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBeckyMail::TranslateFolderName(const nsAString & aFolderName,
+ nsAString & _retval)
+{
+ return nsBeckyUtils::TranslateFolderName(aFolderName, _retval);
+}
+
diff --git a/mailnews/import/becky/src/nsBeckyMail.h b/mailnews/import/becky/src/nsBeckyMail.h
new file mode 100644
index 000000000..ae287a05f
--- /dev/null
+++ b/mailnews/import/becky/src/nsBeckyMail.h
@@ -0,0 +1,45 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 nsBeckyMail_h___
+#define nsBeckyMail_h___
+
+#include "nsIImportMail.h"
+
+class nsIFile;
+class nsIMutableArray;
+class nsIMsgFolder;
+
+class nsBeckyMail final : public nsIImportMail
+{
+public:
+ nsBeckyMail();
+ static nsresult Create(nsIImportMail **aImport);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIIMPORTMAIL
+
+private:
+ virtual ~nsBeckyMail();
+
+ uint32_t mReadBytes;
+
+ nsresult CollectMailboxesInDirectory(nsIFile *aDirectory,
+ uint32_t aDepth,
+ nsIMutableArray *aCollected);
+ nsresult CollectMailboxesInFolderListFile(nsIFile *aListFile,
+ uint32_t aDepth,
+ nsIMutableArray *aCollected);
+ nsresult AppendMailboxDescriptor(nsIFile *aEntry,
+ const nsString &aName,
+ uint32_t aDepth,
+ nsIMutableArray *aCollected);
+ nsresult ImportMailFile(nsIFile *aMailFile,
+ nsIMsgFolder *aDestination);
+ nsresult CreateMailboxDescriptor(nsIImportMailboxDescriptor **aDescriptor);
+ nsresult GetMailboxName(nsIFile *aMailbox, nsAString &aName);
+};
+
+#endif /* nsBeckyMail_h___ */
diff --git a/mailnews/import/becky/src/nsBeckySettings.cpp b/mailnews/import/becky/src/nsBeckySettings.cpp
new file mode 100644
index 000000000..8e1cab960
--- /dev/null
+++ b/mailnews/import/becky/src/nsBeckySettings.cpp
@@ -0,0 +1,471 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 "nsMsgBaseCID.h"
+#include "nsMsgCompCID.h"
+#include "nsIMsgAccountManager.h"
+#include "nsServiceManagerUtils.h"
+#include "nsIINIParser.h"
+#include "nsISmtpService.h"
+#include "nsISmtpServer.h"
+#include "nsIPop3IncomingServer.h"
+#include "nsIStringEnumerator.h"
+#include "nsIInputStream.h"
+#include "nsIOutputStream.h"
+#include "nsILineInputStream.h"
+#include "nsNetUtil.h"
+#include "nsString.h"
+#include "msgCore.h"
+#include "nsIStringBundle.h"
+
+#include "nsBeckySettings.h"
+#include "nsBeckyStringBundle.h"
+#include "nsBeckyUtils.h"
+
+NS_IMPL_ISUPPORTS(nsBeckySettings, nsIImportSettings)
+
+nsresult
+nsBeckySettings::Create(nsIImportSettings **aImport)
+{
+ NS_ENSURE_ARG_POINTER(aImport);
+
+ *aImport = new nsBeckySettings();
+
+ NS_ADDREF(*aImport);
+ return NS_OK;
+}
+
+nsBeckySettings::nsBeckySettings()
+{
+}
+
+nsBeckySettings::~nsBeckySettings()
+{
+}
+
+NS_IMETHODIMP
+nsBeckySettings::AutoLocate(char16_t **aDescription,
+ nsIFile **aLocation,
+ bool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(aDescription);
+ NS_ENSURE_ARG_POINTER(aLocation);
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ *aDescription =
+ nsBeckyStringBundle::GetStringByName(u"BeckyImportName");
+ *aLocation = nullptr;
+ *_retval = false;
+
+ nsCOMPtr<nsIFile> location;
+ nsresult rv = nsBeckyUtils::GetDefaultMailboxINIFile(getter_AddRefs(location));
+ if (NS_FAILED(rv))
+ location = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
+ else
+ *_retval = true;
+
+ location.forget(aLocation);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBeckySettings::SetLocation(nsIFile *aLocation)
+{
+ mLocation = aLocation;
+ return NS_OK;
+}
+
+nsresult
+nsBeckySettings::CreateParser()
+{
+ if (!mLocation) {
+ nsresult rv = nsBeckyUtils::GetDefaultMailboxINIFile(getter_AddRefs(mLocation));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ // nsIINIParser accepts only UTF-8 encoding, so we need to convert the file
+ // first.
+ nsresult rv;
+ rv = nsBeckyUtils::ConvertToUTF8File(mLocation, getter_AddRefs(mConvertedFile));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return nsBeckyUtils::CreateINIParserForFile(mConvertedFile,
+ getter_AddRefs(mParser));
+}
+
+nsresult
+nsBeckySettings::CreateSmtpServer(const nsCString &aUserName,
+ const nsCString &aServerName,
+ nsISmtpServer **aServer,
+ bool *existing)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsISmtpService> smtpService = do_GetService(NS_SMTPSERVICE_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsISmtpServer> server;
+ rv = smtpService->FindServer(aUserName.get(),
+ aServerName.get(),
+ getter_AddRefs(server));
+
+ if (NS_FAILED(rv) || !server) {
+ rv = smtpService->CreateServer(getter_AddRefs(server));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ server->SetHostname(aServerName);
+ server->SetUsername(aUserName);
+ *existing = false;
+ } else {
+ *existing = true;
+ }
+
+ server.forget(aServer);
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckySettings::CreateIncomingServer(const nsCString &aUserName,
+ const nsCString &aServerName,
+ const nsCString &aProtocol,
+ nsIMsgIncomingServer **aServer)
+{
+ nsresult rv;
+ nsCOMPtr<nsIMsgAccountManager> accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIMsgIncomingServer> incomingServer;
+ rv = accountManager->FindServer(aUserName,
+ aServerName,
+ aProtocol,
+ getter_AddRefs(incomingServer));
+
+ if (NS_FAILED(rv) || !incomingServer) {
+ rv = accountManager->CreateIncomingServer(aUserName,
+ aServerName,
+ aProtocol,
+ getter_AddRefs(incomingServer));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ incomingServer.forget(aServer);
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckySettings::SetupSmtpServer(nsISmtpServer **aServer)
+{
+ nsresult rv;
+ nsAutoCString userName, serverName;
+
+ mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("SMTPServer"),
+ serverName);
+ mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("UserID"),
+ userName);
+
+ nsCOMPtr<nsISmtpServer> server;
+ bool existing = false;
+ rv = CreateSmtpServer(userName, serverName, getter_AddRefs(server), &existing);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // If we already have an existing server, do not touch it's settings.
+ if (existing) {
+ server.forget(aServer);
+ return NS_OK;
+ }
+
+ nsAutoCString value;
+ rv = mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("SMTPPort"),
+ value);
+ int32_t port = 25;
+ if (NS_SUCCEEDED(rv)) {
+ nsresult errorCode;
+ port = value.ToInteger(&errorCode, 10);
+ }
+ server->SetPort(port);
+
+ mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("SSLSMTP"),
+ value);
+ if (value.Equals("1"))
+ server->SetSocketType(nsMsgSocketType::SSL);
+
+ mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("SMTPAUTH"),
+ value);
+ if (value.Equals("1")) {
+ mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("SMTPAUTHMODE"),
+ value);
+ nsMsgAuthMethodValue authMethod = nsMsgAuthMethod::none;
+ if (value.Equals("1")) {
+ authMethod = nsMsgAuthMethod::passwordEncrypted;
+ } else if (value.Equals("2") ||
+ value.Equals("4") ||
+ value.Equals("6")) {
+ authMethod = nsMsgAuthMethod::passwordCleartext;
+ } else {
+ authMethod = nsMsgAuthMethod::anything;
+ }
+ server->SetAuthMethod(authMethod);
+ }
+
+ server.forget(aServer);
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckySettings::SetPop3ServerProperties(nsIMsgIncomingServer *aServer)
+{
+ nsCOMPtr<nsIPop3IncomingServer> pop3Server = do_QueryInterface(aServer);
+
+ nsAutoCString value;
+ mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("POP3Auth"),
+ value); // 0: plain, 1: APOP, 2: CRAM-MD5, 3: NTLM
+ nsMsgAuthMethodValue authMethod;
+ if (value.IsEmpty() || value.Equals("0")) {
+ authMethod = nsMsgAuthMethod::passwordCleartext;
+ } else if (value.Equals("1")) {
+ authMethod = nsMsgAuthMethod::old;
+ } else if (value.Equals("2")) {
+ authMethod = nsMsgAuthMethod::passwordEncrypted;
+ } else if (value.Equals("3")) {
+ authMethod = nsMsgAuthMethod::NTLM;
+ } else {
+ authMethod = nsMsgAuthMethod::none;
+ }
+ aServer->SetAuthMethod(authMethod);
+
+ mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("LeaveServer"),
+ value);
+ if (value.Equals("1")) {
+ pop3Server->SetLeaveMessagesOnServer(true);
+ nsresult rv = mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("KeepDays"),
+ value);
+ if (NS_FAILED(rv))
+ return NS_OK;
+
+ nsresult errorCode;
+ int32_t leftDays = value.ToInteger(&errorCode, 10);
+ if (NS_SUCCEEDED(errorCode)) {
+ pop3Server->SetNumDaysToLeaveOnServer(leftDays);
+ pop3Server->SetDeleteByAgeFromServer(true);
+ }
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckySettings::SetupIncomingServer(nsIMsgIncomingServer **aServer)
+{
+ nsAutoCString value;
+ mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("Protocol"),
+ value);
+ nsCString protocol;
+ if (value.Equals("1")) {
+ protocol = NS_LITERAL_CSTRING("imap");
+ } else {
+ protocol = NS_LITERAL_CSTRING("pop3");
+ }
+
+ nsAutoCString userName, serverName;
+ mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("MailServer"),
+ serverName);
+ mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("UserID"),
+ userName);
+
+ nsresult rv;
+ nsCOMPtr<nsIMsgIncomingServer> server;
+ rv = CreateIncomingServer(userName, serverName, protocol, getter_AddRefs(server));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool isSecure = false;
+ int32_t port = 0;
+ nsresult errorCode;
+ if (protocol.EqualsLiteral("pop3")) {
+ SetPop3ServerProperties(server);
+ rv = mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("POP3Port"),
+ value);
+ if (NS_SUCCEEDED(rv))
+ port = value.ToInteger(&errorCode, 10);
+ else
+ port = 110;
+ mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("SSLPOP"),
+ value);
+ if (value.Equals("1"))
+ isSecure = true;
+ } else if (protocol.EqualsLiteral("imap")) {
+ rv = mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("IMAP4Port"),
+ value);
+ if (NS_SUCCEEDED(rv))
+ port = value.ToInteger(&errorCode, 10);
+ else
+ port = 143;
+ mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("SSLIMAP"),
+ value);
+ if (value.Equals("1"))
+ isSecure = true;
+ }
+
+ server->SetPort(port);
+ if (isSecure)
+ server->SetSocketType(nsMsgSocketType::SSL);
+
+ mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("CheckInt"),
+ value);
+ if (value.Equals("1"))
+ server->SetDoBiff(true);
+ rv = mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("CheckEvery"),
+ value);
+ if (NS_SUCCEEDED(rv)) {
+ int32_t minutes = value.ToInteger(&errorCode, 10);
+ if (NS_SUCCEEDED(errorCode))
+ server->SetBiffMinutes(minutes);
+ }
+
+ server.forget(aServer);
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckySettings::CreateIdentity(nsIMsgIdentity **aIdentity)
+{
+ nsAutoCString email, fullName, identityName, bccAddress;
+
+ mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("Name"),
+ identityName);
+ mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("YourName"),
+ fullName);
+ mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("MailAddress"),
+ email);
+ mParser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("PermBcc"),
+ bccAddress);
+
+ nsresult rv;
+ nsCOMPtr<nsIMsgAccountManager> accountManager =
+ do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIMsgIdentity> identity;
+ rv = accountManager->CreateIdentity(getter_AddRefs(identity));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ identity->SetLabel(NS_ConvertUTF8toUTF16(identityName));
+ identity->SetFullName(NS_ConvertUTF8toUTF16(fullName));
+ identity->SetEmail(email);
+ if (!bccAddress.IsEmpty()) {
+ identity->SetDoBcc(true);
+ identity->SetDoBccList(bccAddress);
+ }
+
+ identity.forget(aIdentity);
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckySettings::CreateAccount(nsIMsgIdentity *aIdentity,
+ nsIMsgIncomingServer *aIncomingServer,
+ nsIMsgAccount **aAccount)
+{
+ nsresult rv;
+ nsCOMPtr<nsIMsgAccountManager> accountManager =
+ do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIMsgAccount> account;
+ rv = accountManager->CreateAccount(getter_AddRefs(account));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = account->AddIdentity(aIdentity);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = account->SetIncomingServer(aIncomingServer);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ account.forget(aAccount);
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckySettings::RemoveConvertedFile()
+{
+ if (mConvertedFile) {
+ bool exists;
+ mConvertedFile->Exists(&exists);
+ if (exists)
+ mConvertedFile->Remove(false);
+ mConvertedFile = nullptr;
+ }
+ return NS_OK;
+}
+
+#define NS_RETURN_IF_FAILED_WITH_REMOVE_CONVERTED_FILE(expr, rv) \
+ if (NS_FAILED(expr)) { \
+ RemoveConvertedFile(); \
+ return rv; \
+ }
+
+NS_IMETHODIMP
+nsBeckySettings::Import(nsIMsgAccount **aLocalMailAccount,
+ bool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(aLocalMailAccount);
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ nsresult rv = CreateParser();
+ NS_RETURN_IF_FAILED_WITH_REMOVE_CONVERTED_FILE(rv, rv);
+
+ nsCOMPtr<nsIMsgIncomingServer> incomingServer;
+ rv = SetupIncomingServer(getter_AddRefs(incomingServer));
+ NS_RETURN_IF_FAILED_WITH_REMOVE_CONVERTED_FILE(rv, rv);
+
+ nsCOMPtr<nsISmtpServer> smtpServer;
+ rv = SetupSmtpServer(getter_AddRefs(smtpServer));
+ NS_RETURN_IF_FAILED_WITH_REMOVE_CONVERTED_FILE(rv, rv);
+
+ nsCOMPtr<nsIMsgIdentity> identity;
+ rv = CreateIdentity(getter_AddRefs(identity));
+ NS_RETURN_IF_FAILED_WITH_REMOVE_CONVERTED_FILE(rv, rv);
+
+ nsAutoCString smtpKey;
+ smtpServer->GetKey(getter_Copies(smtpKey));
+ identity->SetSmtpServerKey(smtpKey);
+
+ nsCOMPtr<nsIMsgAccount> account;
+ rv = CreateAccount(identity, incomingServer, getter_AddRefs(account));
+ NS_RETURN_IF_FAILED_WITH_REMOVE_CONVERTED_FILE(rv, rv);
+
+ RemoveConvertedFile();
+ if (aLocalMailAccount)
+ account.forget(aLocalMailAccount);
+ *_retval = true;
+ return NS_OK;
+}
+
diff --git a/mailnews/import/becky/src/nsBeckySettings.h b/mailnews/import/becky/src/nsBeckySettings.h
new file mode 100644
index 000000000..19e7d45ed
--- /dev/null
+++ b/mailnews/import/becky/src/nsBeckySettings.h
@@ -0,0 +1,52 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 nsBeckySettings_h___
+#define nsBeckySettings_h___
+
+#include "nsIImportSettings.h"
+#include "nsIFile.h"
+#include "nsIINIParser.h"
+
+class nsIMsgIncomingServer;
+class nsIMsgIdentity;
+class nsISmtpServer;
+
+class nsBeckySettings final : public nsIImportSettings
+{
+public:
+ nsBeckySettings();
+ static nsresult Create(nsIImportSettings **aImport);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIIMPORTSETTINGS
+
+private:
+ virtual ~nsBeckySettings();
+
+ nsCOMPtr<nsIFile> mLocation;
+ nsCOMPtr<nsIFile> mConvertedFile;
+ nsCOMPtr<nsIINIParser> mParser;
+
+ nsresult CreateParser();
+ nsresult CreateIdentity(nsIMsgIdentity **aIdentity);
+ nsresult CreateAccount(nsIMsgIdentity *aIdentity,
+ nsIMsgIncomingServer *aIncomingServer,
+ nsIMsgAccount **aAccount);
+ nsresult CreateSmtpServer(const nsCString &aUserName,
+ const nsCString &aServerName,
+ nsISmtpServer **aServer,
+ bool *existing);
+ nsresult CreateIncomingServer(const nsCString &aUserName,
+ const nsCString &aServerName,
+ const nsCString &aProtocol,
+ nsIMsgIncomingServer **aServer);
+ nsresult SetupIncomingServer(nsIMsgIncomingServer **aServer);
+ nsresult SetupSmtpServer(nsISmtpServer **aServer);
+ nsresult SetPop3ServerProperties(nsIMsgIncomingServer *aServer);
+ nsresult RemoveConvertedFile();
+};
+
+#endif /* nsBeckySettings_h___ */
diff --git a/mailnews/import/becky/src/nsBeckyStringBundle.cpp b/mailnews/import/becky/src/nsBeckyStringBundle.cpp
new file mode 100644
index 000000000..41209dff5
--- /dev/null
+++ b/mailnews/import/becky/src/nsBeckyStringBundle.cpp
@@ -0,0 +1,74 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 "prprf.h"
+#include "prmem.h"
+#include "nsCOMPtr.h"
+#include "nsIStringBundle.h"
+#include "nsIServiceManager.h"
+#include "nsIURI.h"
+#include "nsServiceManagerUtils.h"
+#include "nsXPCOMCIDInternal.h"
+
+#include "nsBeckyStringBundle.h"
+
+#define BECKY_MESSAGES_URL "chrome://messenger/locale/beckyImportMsgs.properties"
+
+nsIStringBundle *nsBeckyStringBundle::mBundle = nullptr;
+
+nsIStringBundle *
+nsBeckyStringBundle::GetStringBundle(void)
+{
+ if (mBundle)
+ return mBundle;
+
+ nsresult rv;
+ nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
+ if (NS_SUCCEEDED(rv) && bundleService)
+ rv = bundleService->CreateBundle(BECKY_MESSAGES_URL, &mBundle);
+
+ return mBundle;
+}
+
+void
+nsBeckyStringBundle::EnsureStringBundle(void)
+{
+ if (!mBundle)
+ (void) GetStringBundle();
+}
+
+char16_t *
+nsBeckyStringBundle::GetStringByName(const char16_t *aName)
+{
+ EnsureStringBundle();
+
+ char16_t *string = nullptr;
+ if (mBundle)
+ mBundle->GetStringFromName(aName, &string);
+
+ return string;
+}
+
+nsresult
+nsBeckyStringBundle::FormatStringFromName(const char16_t *name,
+ const char16_t **params,
+ uint32_t length,
+ char16_t **_retval)
+{
+ EnsureStringBundle();
+
+ return mBundle->FormatStringFromName(name,
+ params,
+ length,
+ _retval);
+}
+
+void
+nsBeckyStringBundle::Cleanup(void)
+{
+ if (mBundle)
+ mBundle->Release();
+ mBundle = nullptr;
+}
diff --git a/mailnews/import/becky/src/nsBeckyStringBundle.h b/mailnews/import/becky/src/nsBeckyStringBundle.h
new file mode 100644
index 000000000..190208c9d
--- /dev/null
+++ b/mailnews/import/becky/src/nsBeckyStringBundle.h
@@ -0,0 +1,33 @@
+/* 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 _nsBeckyStringBundle_H__
+#define _nsBeckyStringBundle_H__
+
+#include "nsString.h"
+
+class nsIStringBundle;
+
+class nsBeckyStringBundle final {
+public:
+ static char16_t *GetStringByName(const char16_t *name);
+ static nsresult FormatStringFromName(const char16_t *name,
+ const char16_t **params,
+ uint32_t length,
+ char16_t **_retval);
+ static nsIStringBundle * GetStringBundle(void); // don't release
+ static void EnsureStringBundle(void);
+ static void Cleanup(void);
+private:
+ static nsIStringBundle *mBundle;
+};
+
+#define BECKYIMPORT_NAME 2000
+#define BECKYIMPORT_DESCRIPTION 2001
+#define BECKYIMPORT_MAILBOX_SUCCESS 2002
+#define BECKYIMPORT_MAILBOX_BADPARAM 2003
+#define BECKYIMPORT_MAILBOX_CONVERTERROR 2004
+#define BECKYIMPORT_ADDRESS_SUCCESS 2005
+
+
+#endif /* _nsBeckyStringBundle_H__ */
diff --git a/mailnews/import/becky/src/nsBeckyUtils.cpp b/mailnews/import/becky/src/nsBeckyUtils.cpp
new file mode 100644
index 000000000..2e9af84a5
--- /dev/null
+++ b/mailnews/import/becky/src/nsBeckyUtils.cpp
@@ -0,0 +1,334 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 "nsCOMPtr.h"
+#include "nsIFile.h"
+#include "nsISimpleEnumerator.h"
+#include "nsServiceManagerUtils.h"
+#include "nsComponentManagerUtils.h"
+#include "nsString.h"
+#include "nsIUTF8ConverterService.h"
+#include "nsUConvCID.h"
+#include "nsNativeCharsetUtils.h"
+#include "nsIInputStream.h"
+#include "nsIOutputStream.h"
+#include "nsILineInputStream.h"
+#include "nsIConverterInputStream.h"
+#include "nsIConverterOutputStream.h"
+#include "nsMsgI18N.h"
+#include "nsNetUtil.h"
+#include "nsIINIParser.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsDirectoryServiceUtils.h"
+#include "nsMsgUtils.h"
+#include "msgCore.h"
+#include "nsIImportMail.h"
+#include "nsThreadUtils.h"
+
+#include "nsBeckyUtils.h"
+
+nsresult
+nsBeckyUtils::FindUserDirectoryOnWindows7(nsIFile **aLocation)
+{
+ NS_ENSURE_ARG_POINTER(aLocation);
+
+ nsresult rv;
+ nsCOMPtr<nsIFile> directory;
+ rv = GetSpecialDirectoryWithFileName(NS_WIN_DOCUMENTS_DIR,
+ "Becky",
+ getter_AddRefs(directory));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool exists = false;
+ rv = directory->Exists(&exists);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!exists)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ bool isDirectory = false;
+ rv = directory->IsDirectory(&isDirectory);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!isDirectory)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ directory.forget(aLocation);
+ return NS_OK;
+}
+
+nsresult
+nsBeckyUtils::FindUserDirectoryOnWindowsXP(nsIFile **aLocation)
+{
+ NS_ENSURE_ARG_POINTER(aLocation);
+
+ nsresult rv;
+ nsCOMPtr<nsIFile> directory = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = directory->InitWithPath(NS_LITERAL_STRING("C:\\Becky!"));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool exists = false;
+ rv = directory->Exists(&exists);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!exists)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ bool isDirectory = false;
+ rv = directory->IsDirectory(&isDirectory);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!isDirectory)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ nsCOMPtr<nsISimpleEnumerator> entries;
+ rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool more;
+ nsCOMPtr<nsISupports> entry;
+ while (NS_SUCCEEDED(entries->HasMoreElements(&more)) && more) {
+ rv = entries->GetNext(getter_AddRefs(entry));
+
+ nsCOMPtr<nsIFile> file = do_QueryInterface(entry, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool isDirectory = false;
+ rv = file->IsDirectory(&isDirectory);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (isDirectory) {
+ file.forget(aLocation);
+ return NS_OK;
+ }
+ }
+
+ directory.forget(aLocation);
+ return NS_OK;
+}
+
+nsresult
+nsBeckyUtils::FindUserDirectory(nsIFile **aLocation)
+{
+ nsresult rv = FindUserDirectoryOnWindows7(aLocation);
+ if (rv == NS_ERROR_FILE_NOT_FOUND) {
+ rv = FindUserDirectoryOnWindowsXP(aLocation);
+ }
+ return rv;
+}
+
+nsresult
+nsBeckyUtils::ConvertNativeStringToUTF8(const nsACString& aOriginal,
+ nsACString& _retval)
+{
+ nsresult rv;
+ nsAutoString unicodeString;
+ rv = NS_CopyNativeToUnicode(aOriginal, unicodeString);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ CopyUTF16toUTF8(unicodeString, _retval);
+ return NS_OK;
+}
+
+nsresult
+nsBeckyUtils::CreateLineInputStream(nsIFile *aFile,
+ nsILineInputStream **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ nsCOMPtr<nsIInputStream> inputStream;
+ nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), aFile);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return CallQueryInterface(inputStream, _retval);
+}
+
+nsresult
+nsBeckyUtils::GetFolderListFile(nsIFile *aLocation, nsIFile **_retval)
+{
+ nsresult rv;
+ nsCOMPtr<nsIFile> folderListFile;
+ rv = aLocation->Clone(getter_AddRefs(folderListFile));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = folderListFile->Append(NS_LITERAL_STRING("Folder.lst"));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool exists;
+ rv = folderListFile->Exists(&exists);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!exists)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ folderListFile.forget(_retval);
+ return NS_OK;
+}
+
+nsresult
+nsBeckyUtils::GetDefaultFolderName(nsIFile *aFolderListFile, nsACString& name)
+{
+ nsresult rv;
+ nsCOMPtr<nsILineInputStream> lineStream;
+ rv = CreateLineInputStream(aFolderListFile, getter_AddRefs(lineStream));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool more = true;
+ rv = lineStream->ReadLine(name, &more);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+nsresult
+nsBeckyUtils::GetDefaultMailboxDirectory(nsIFile **_retval)
+{
+ nsCOMPtr<nsIFile> userDirectory;
+ nsresult rv = FindUserDirectory(getter_AddRefs(userDirectory));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIFile> folderListFile;
+ rv = GetFolderListFile(userDirectory, getter_AddRefs(folderListFile));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoCString defaultFolderName;
+ rv = GetDefaultFolderName(folderListFile, defaultFolderName);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = userDirectory->AppendNative(defaultFolderName);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool exists;
+ rv = userDirectory->Exists(&exists);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!exists)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ bool isDirectory = false;
+ rv = userDirectory->IsDirectory(&isDirectory);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!isDirectory)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ userDirectory.forget(_retval);
+ return NS_OK;
+}
+
+nsresult
+nsBeckyUtils::GetDefaultMailboxINIFile(nsIFile **_retval)
+{
+ nsresult rv;
+ nsCOMPtr<nsIFile> mailboxDirectory;
+ rv = GetDefaultMailboxDirectory(getter_AddRefs(mailboxDirectory));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return GetMailboxINIFile(mailboxDirectory, _retval);
+}
+
+nsresult
+nsBeckyUtils::GetMailboxINIFile(nsIFile *aDirectory, nsIFile **_retval)
+{
+ nsresult rv;
+ nsCOMPtr<nsIFile> target;
+ rv = aDirectory->Clone(getter_AddRefs(target));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = target->Append(NS_LITERAL_STRING("Mailbox.ini"));
+ NS_ENSURE_SUCCESS(rv, rv);
+ bool exists;
+ rv = target->Exists(&exists);
+ if (!exists)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ target.forget(_retval);
+ return NS_OK;
+}
+
+nsresult
+nsBeckyUtils::CreateINIParserForFile(nsIFile *aFile,
+ nsIINIParser **aParser)
+{
+ nsresult rv;
+ nsCOMPtr<nsIINIParserFactory> factory =
+ do_GetService("@mozilla.org/xpcom/ini-processor-factory;1", &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return factory->CreateINIParser(aFile, aParser);
+}
+
+nsresult
+nsBeckyUtils::GetMailboxNameFromINIFile(nsIFile *aFile, nsCString &aName)
+{
+ nsresult rv;
+ nsCOMPtr<nsIINIParser> parser;
+ rv = CreateINIParserForFile(aFile, getter_AddRefs(parser));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return parser->GetString(NS_LITERAL_CSTRING("Account"),
+ NS_LITERAL_CSTRING("Name"),
+ aName);
+}
+
+nsresult
+nsBeckyUtils::ConvertToUTF8File(nsIFile *aSourceFile,
+ nsIFile **_retval)
+{
+ nsresult rv;
+ nsCOMPtr<nsIFile> convertedFile;
+ rv = GetSpecialDirectoryWithFileName(NS_OS_TEMP_DIR,
+ "thunderbird-becky-import",
+ getter_AddRefs(convertedFile));
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = convertedFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIInputStream> source;
+ rv = NS_NewLocalFileInputStream(getter_AddRefs(source), aSourceFile);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIOutputStream> destination;
+ rv = NS_NewLocalFileOutputStream(getter_AddRefs(destination),
+ convertedFile);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ const uint32_t kBlock = 8192;
+
+ nsCOMPtr<nsIConverterInputStream> convertedInput =
+ do_CreateInstance("@mozilla.org/intl/converter-input-stream;1");
+ convertedInput->Init(source, nsMsgI18NFileSystemCharset(), kBlock, 0x0000);
+
+ nsCOMPtr<nsIConverterOutputStream> convertedOutput =
+ do_CreateInstance("@mozilla.org/intl/converter-output-stream;1");
+ convertedOutput->Init(destination, "UTF-8", kBlock, 0x0000);
+
+ char16_t *line = (char16_t *)moz_xmalloc(kBlock);
+ uint32_t readBytes = kBlock;
+ bool writtenBytes;
+ while (readBytes == kBlock) {
+ rv = convertedInput->Read(line, kBlock, &readBytes);
+ rv = convertedOutput->Write(readBytes, line, &writtenBytes);
+ }
+ convertedOutput->Close();
+ convertedInput->Close();
+
+ convertedFile.forget(_retval);
+ return NS_OK;
+}
+
+nsresult
+nsBeckyUtils::TranslateFolderName(const nsAString & aFolderName,
+ nsAString & _retval)
+{
+ if (aFolderName.LowerCaseEqualsLiteral("!trash"))
+ _retval = NS_LITERAL_STRING(kDestTrashFolderName);
+ else if (aFolderName.LowerCaseEqualsLiteral("!!!!inbox"))
+ _retval = NS_LITERAL_STRING(kDestInboxFolderName);
+ else if (aFolderName.LowerCaseEqualsLiteral("!!!!outbox"))
+ _retval = NS_LITERAL_STRING(kDestSentFolderName);
+ else if (aFolderName.LowerCaseEqualsLiteral("!!!!unsent"))
+ _retval = NS_LITERAL_STRING(kDestUnsentMessagesFolderName);
+ else
+ _retval = aFolderName;
+
+ return NS_OK;
+}
diff --git a/mailnews/import/becky/src/nsBeckyUtils.h b/mailnews/import/becky/src/nsBeckyUtils.h
new file mode 100644
index 000000000..8b6e3a542
--- /dev/null
+++ b/mailnews/import/becky/src/nsBeckyUtils.h
@@ -0,0 +1,37 @@
+/* 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 _nsBeckyUtils_H__
+#define _nsBeckyUtils_H__
+
+class nsIFile;
+class nsILineInputStream;
+class nsIINIParser;
+
+class nsBeckyUtils final {
+public:
+ static nsresult FindUserDirectoryOnWindows7(nsIFile **aLocation);
+ static nsresult FindUserDirectoryOnWindowsXP(nsIFile **aLocation);
+ static nsresult FindUserDirectory(nsIFile **aFile);
+ static nsresult ConvertNativeStringToUTF8(const nsACString& aOriginal,
+ nsACString& _retval);
+ static nsresult CreateLineInputStream(nsIFile *aFile,
+ nsILineInputStream **_retval);
+ static nsresult GetDefaultMailboxDirectory(nsIFile **_retval);
+ static nsresult GetFolderListFile(nsIFile *aLocation,
+ nsIFile **_retval);
+ static nsresult GetDefaultFolderName(nsIFile *aFolderListFile,
+ nsACString& name);
+ static nsresult GetDefaultMailboxINIFile(nsIFile **_retval);
+ static nsresult GetMailboxINIFile(nsIFile *aDirectory, nsIFile **_retval);
+ static nsresult CreateINIParserForFile(nsIFile *aFile,
+ nsIINIParser **aParser);
+ static nsresult GetMailboxNameFromINIFile(nsIFile *aFile, nsCString &aName);
+ static nsresult ConvertToUTF8File(nsIFile *aSourceFile,
+ nsIFile **_retval);
+ static nsresult TranslateFolderName(const nsAString & aFolderName,
+ nsAString & _retval);
+};
+
+
+#endif /* _nsBeckyUtils_H__ */