summaryrefslogtreecommitdiffstats
path: root/mailnews/import/src/nsImportService.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mailnews/import/src/nsImportService.cpp')
-rw-r--r--mailnews/import/src/nsImportService.cpp583
1 files changed, 583 insertions, 0 deletions
diff --git a/mailnews/import/src/nsImportService.cpp b/mailnews/import/src/nsImportService.cpp
new file mode 100644
index 000000000..0013c1146
--- /dev/null
+++ b/mailnews/import/src/nsImportService.cpp
@@ -0,0 +1,583 @@
+/* -*- 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 "nsICharsetConverterManager.h"
+#include "nsIPlatformCharset.h"
+#include "nsICharsetConverterManager.h"
+
+#include "nsStringGlue.h"
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsMemory.h"
+#include "nsIImportModule.h"
+#include "nsIImportService.h"
+#include "nsImportMailboxDescriptor.h"
+#include "nsImportABDescriptor.h"
+#include "nsIImportGeneric.h"
+#include "nsImportFieldMap.h"
+#include "nsICategoryManager.h"
+#include "nsXPCOM.h"
+#include "nsISupportsPrimitives.h"
+#include "plstr.h"
+#include "prmem.h"
+#include "nsMsgCompCID.h"
+#include "nsThreadUtils.h"
+#include "nsIEditor.h"
+#include "ImportDebug.h"
+#include "nsImportService.h"
+#include "nsImportStringBundle.h"
+#include "nsCRTGlue.h"
+#include "nsServiceManagerUtils.h"
+#include "nsComponentManagerUtils.h"
+#include "nsIMutableArray.h"
+#include "nsIArray.h"
+#include "nsIMsgSend.h"
+#include "nsMsgUtils.h"
+
+PRLogModuleInfo *IMPORTLOGMODULE = nullptr;
+
+static nsIImportService * gImportService = nullptr;
+static const char * kWhitespace = "\b\t\r\n ";
+
+
+////////////////////////////////////////////////////////////////////////
+
+
+nsImportService::nsImportService() : m_pModules(nullptr)
+{
+ // Init logging module.
+ if (!IMPORTLOGMODULE)
+ IMPORTLOGMODULE = PR_NewLogModule("IMPORT");
+ IMPORT_LOG0("* nsImport Service Created\n");
+
+ m_didDiscovery = false;
+ m_pDecoder = nullptr;
+ m_pEncoder = nullptr;
+
+ nsresult rv = nsImportStringBundle::GetStringBundle(IMPORT_MSGS_URL, getter_AddRefs(m_stringBundle));
+ if (NS_FAILED(rv))
+ IMPORT_LOG0("Failed to get string bundle for Importing Mail");
+}
+
+
+nsImportService::~nsImportService()
+{
+ NS_IF_RELEASE(m_pDecoder);
+ NS_IF_RELEASE(m_pEncoder);
+
+ gImportService = nullptr;
+
+ if (m_pModules != nullptr)
+ delete m_pModules;
+
+ IMPORT_LOG0("* nsImport Service Deleted\n");
+}
+
+
+
+NS_IMPL_ISUPPORTS(nsImportService, nsIImportService)
+
+
+NS_IMETHODIMP nsImportService::DiscoverModules(void)
+{
+ m_didDiscovery = false;
+ return DoDiscover();
+}
+
+NS_IMETHODIMP nsImportService::CreateNewFieldMap(nsIImportFieldMap **_retval)
+{
+ return nsImportFieldMap::Create(m_stringBundle, nullptr, NS_GET_IID(nsIImportFieldMap), (void**)_retval);
+}
+
+NS_IMETHODIMP nsImportService::CreateNewMailboxDescriptor(nsIImportMailboxDescriptor **_retval)
+{
+ return nsImportMailboxDescriptor::Create(nullptr, NS_GET_IID(nsIImportMailboxDescriptor), (void**)_retval);
+}
+
+NS_IMETHODIMP nsImportService::CreateNewABDescriptor(nsIImportABDescriptor **_retval)
+{
+ return nsImportABDescriptor::Create(nullptr, NS_GET_IID(nsIImportABDescriptor), (void**)_retval);
+}
+
+extern nsresult NS_NewGenericMail(nsIImportGeneric** aImportGeneric);
+
+NS_IMETHODIMP nsImportService::CreateNewGenericMail(nsIImportGeneric **_retval)
+{
+ NS_PRECONDITION(_retval != nullptr, "null ptr");
+ if (! _retval)
+ return NS_ERROR_NULL_POINTER;
+
+ return NS_NewGenericMail(_retval);
+}
+
+extern nsresult NS_NewGenericAddressBooks(nsIImportGeneric** aImportGeneric);
+
+NS_IMETHODIMP nsImportService::CreateNewGenericAddressBooks(nsIImportGeneric **_retval)
+{
+ NS_PRECONDITION(_retval != nullptr, "null ptr");
+ if (! _retval)
+ return NS_ERROR_NULL_POINTER;
+
+ return NS_NewGenericAddressBooks(_retval);
+}
+
+
+NS_IMETHODIMP nsImportService::GetModuleCount(const char *filter, int32_t *_retval)
+{
+ NS_PRECONDITION(_retval != nullptr, "null ptr");
+ if (! _retval)
+ return NS_ERROR_NULL_POINTER;
+
+ DoDiscover();
+
+ if (m_pModules != nullptr) {
+ ImportModuleDesc * pDesc;
+ int32_t count = 0;
+ for (int32_t i = 0; i < m_pModules->GetCount(); i++) {
+ pDesc = m_pModules->GetModuleDesc(i);
+ if (pDesc->SupportsThings(filter))
+ count++;
+ }
+ *_retval = count;
+ }
+ else
+ *_retval = 0;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImportService::GetModuleWithCID(const nsCID& cid, nsIImportModule **ppModule)
+{
+ NS_PRECONDITION(ppModule != nullptr, "null ptr");
+ if (!ppModule)
+ return NS_ERROR_NULL_POINTER;
+
+ *ppModule = nullptr;
+ nsresult rv = DoDiscover();
+ if (NS_FAILED(rv))
+ return rv;
+ if (m_pModules == nullptr)
+ return NS_ERROR_FAILURE;
+ int32_t cnt = m_pModules->GetCount();
+ ImportModuleDesc *pDesc;
+ for (int32_t i = 0; i < cnt; i++) {
+ pDesc = m_pModules->GetModuleDesc(i);
+ if (!pDesc)
+ return NS_ERROR_FAILURE;
+ if (pDesc->GetCID().Equals(cid)) {
+ *ppModule = pDesc->GetModule();
+
+ IMPORT_LOG0("* nsImportService::GetSpecificModule - attempted to load module\n");
+
+ if (*ppModule == nullptr)
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+ }
+ }
+
+ IMPORT_LOG0("* nsImportService::GetSpecificModule - module not found\n");
+
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP nsImportService::GetModuleInfo(const char *filter, int32_t index, char16_t **name, char16_t **moduleDescription)
+{
+ NS_PRECONDITION(name != nullptr, "null ptr");
+ NS_PRECONDITION(moduleDescription != nullptr, "null ptr");
+ if (!name || !moduleDescription)
+ return NS_ERROR_NULL_POINTER;
+
+ *name = nullptr;
+ *moduleDescription = nullptr;
+
+ DoDiscover();
+ if (!m_pModules)
+ return NS_ERROR_FAILURE;
+
+ if ((index < 0) || (index >= m_pModules->GetCount()))
+ return NS_ERROR_FAILURE;
+
+ ImportModuleDesc * pDesc;
+ int32_t count = 0;
+ for (int32_t i = 0; i < m_pModules->GetCount(); i++) {
+ pDesc = m_pModules->GetModuleDesc(i);
+ if (pDesc->SupportsThings(filter)) {
+ if (count == index) {
+ *name = NS_strdup(pDesc->GetName());
+ *moduleDescription = NS_strdup(pDesc->GetDescription());
+ return NS_OK;
+ }
+ else
+ count++;
+ }
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP nsImportService::GetModuleName(const char *filter, int32_t index, char16_t **_retval)
+{
+ NS_PRECONDITION(_retval != nullptr, "null ptr");
+ if (!_retval)
+ return NS_ERROR_NULL_POINTER;
+
+ *_retval = nullptr;
+
+ DoDiscover();
+ if (!m_pModules)
+ return NS_ERROR_FAILURE;
+
+ if ((index < 0) || (index >= m_pModules->GetCount()))
+ return NS_ERROR_FAILURE;
+
+ ImportModuleDesc * pDesc;
+ int32_t count = 0;
+ for (int32_t i = 0; i < m_pModules->GetCount(); i++) {
+ pDesc = m_pModules->GetModuleDesc(i);
+ if (pDesc->SupportsThings(filter)) {
+ if (count == index) {
+ *_retval = NS_strdup(pDesc->GetName());
+ return NS_OK;
+ }
+ else
+ count++;
+ }
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+
+NS_IMETHODIMP nsImportService::GetModuleDescription(const char *filter, int32_t index, char16_t **_retval)
+{
+ NS_PRECONDITION(_retval != nullptr, "null ptr");
+ if (!_retval)
+ return NS_ERROR_NULL_POINTER;
+
+ *_retval = nullptr;
+
+ DoDiscover();
+ if (!m_pModules)
+ return NS_ERROR_FAILURE;
+
+ if ((index < 0) || (index >= m_pModules->GetCount()))
+ return NS_ERROR_FAILURE;
+
+ ImportModuleDesc * pDesc;
+ int32_t count = 0;
+ for (int32_t i = 0; i < m_pModules->GetCount(); i++) {
+ pDesc = m_pModules->GetModuleDesc(i);
+ if (pDesc->SupportsThings(filter)) {
+ if (count == index) {
+ *_retval = NS_strdup(pDesc->GetDescription());
+ return NS_OK;
+ }
+ else
+ count++;
+ }
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+class nsProxySendRunnable : public mozilla::Runnable
+{
+public:
+ nsProxySendRunnable(nsIMsgIdentity *aIdentity,
+ nsIMsgCompFields *aMsgFields,
+ const char *attachment1_type,
+ const nsACString &attachment1_body,
+ bool aIsDraft,
+ nsIArray *aLoadedAttachments,
+ nsIArray *aEmbeddedAttachments,
+ nsIMsgSendListener *aListener);
+ NS_DECL_NSIRUNNABLE
+private:
+ nsCOMPtr<nsIMsgIdentity> m_identity;
+ nsCOMPtr<nsIMsgCompFields> m_compFields;
+ bool m_isDraft;
+ nsCString m_bodyType;
+ nsCString m_body;
+ nsCOMPtr<nsIArray> m_loadedAttachments;
+ nsCOMPtr<nsIArray> m_embeddedAttachments;
+ nsCOMPtr<nsIMsgSendListener> m_listener;
+
+};
+
+nsProxySendRunnable::nsProxySendRunnable(nsIMsgIdentity *aIdentity,
+ nsIMsgCompFields *aMsgFields,
+ const char *aBodyType,
+ const nsACString &aBody,
+ bool aIsDraft,
+ nsIArray *aLoadedAttachments,
+ nsIArray *aEmbeddedAttachments,
+ nsIMsgSendListener *aListener) :
+ m_identity(aIdentity), m_compFields(aMsgFields),
+ m_isDraft(aIsDraft), m_bodyType(aBodyType),
+ m_body(aBody), m_loadedAttachments(aLoadedAttachments),
+ m_embeddedAttachments(aEmbeddedAttachments),
+ m_listener(aListener)
+{
+}
+
+NS_IMETHODIMP nsProxySendRunnable::Run()
+{
+ nsresult rv;
+ nsCOMPtr<nsIMsgSend> msgSend = do_CreateInstance(NS_MSGSEND_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return msgSend->CreateRFC822Message(m_identity, m_compFields,
+ m_bodyType.get(), m_body,
+ m_isDraft, m_loadedAttachments,
+ m_embeddedAttachments,
+ m_listener);
+}
+
+
+NS_IMETHODIMP
+nsImportService::CreateRFC822Message(nsIMsgIdentity *aIdentity,
+ nsIMsgCompFields *aMsgFields,
+ const char *aBodyType,
+ const nsACString &aBody,
+ bool aIsDraft,
+ nsIArray *aLoadedAttachments,
+ nsIArray *aEmbeddedAttachments,
+ nsIMsgSendListener *aListener)
+{
+ RefPtr<nsProxySendRunnable> runnable =
+ new nsProxySendRunnable(aIdentity,
+ aMsgFields,
+ aBodyType,
+ aBody,
+ aIsDraft,
+ aLoadedAttachments,
+ aEmbeddedAttachments,
+ aListener);
+ // invoke the callback
+ return NS_DispatchToMainThread(runnable);
+}
+
+NS_IMETHODIMP nsImportService::GetModule(const char *filter, int32_t index, nsIImportModule **_retval)
+{
+ NS_PRECONDITION(_retval != nullptr, "null ptr");
+ if (!_retval)
+ return NS_ERROR_NULL_POINTER;
+ *_retval = nullptr;
+
+ DoDiscover();
+ if (!m_pModules)
+ return NS_ERROR_FAILURE;
+
+ if ((index < 0) || (index >= m_pModules->GetCount()))
+ return NS_ERROR_FAILURE;
+
+ ImportModuleDesc * pDesc;
+ int32_t count = 0;
+ for (int32_t i = 0; i < m_pModules->GetCount(); i++) {
+ pDesc = m_pModules->GetModuleDesc(i);
+ if (pDesc->SupportsThings(filter)) {
+ if (count == index) {
+ *_retval = pDesc->GetModule();
+ break;
+ }
+ else
+ count++;
+ }
+ }
+ if (! (*_retval))
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+
+nsresult nsImportService::DoDiscover(void)
+{
+ if (m_didDiscovery)
+ return NS_OK;
+
+ if (m_pModules != nullptr)
+ m_pModules->ClearList();
+
+ nsresult rv;
+
+ nsCOMPtr<nsICategoryManager> catMan = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsISimpleEnumerator> e;
+ rv = catMan->EnumerateCategory("mailnewsimport", getter_AddRefs(e));
+ NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsISupports> supports;
+ nsCOMPtr<nsISupportsCString> contractid;
+ rv = e->GetNext(getter_AddRefs(supports));
+ while (NS_SUCCEEDED(rv) && supports)
+ {
+ contractid = do_QueryInterface(supports);
+ if (!contractid)
+ break;
+
+ nsCString contractIdStr;
+ contractid->ToString(getter_Copies(contractIdStr));
+ nsCString supportsStr;
+ rv = catMan->GetCategoryEntry("mailnewsimport", contractIdStr.get(), getter_Copies(supportsStr));
+ if (NS_SUCCEEDED(rv))
+ LoadModuleInfo(contractIdStr.get(), supportsStr.get());
+ rv = e->GetNext(getter_AddRefs(supports));
+ }
+
+ m_didDiscovery = true;
+
+ return NS_OK;
+}
+
+nsresult nsImportService::LoadModuleInfo(const char *pClsId, const char *pSupports)
+{
+ if (!pClsId || !pSupports)
+ return NS_OK;
+
+ if (m_pModules == nullptr)
+ m_pModules = new nsImportModuleList();
+
+ // load the component and get all of the info we need from it....
+ // then call AddModule
+ nsresult rv;
+
+ nsCID clsId;
+ clsId.Parse(pClsId);
+ nsIImportModule * module;
+ rv = CallCreateInstance(clsId, &module);
+ if (NS_FAILED(rv)) return rv;
+
+ nsString theTitle;
+ nsString theDescription;
+ rv = module->GetName(getter_Copies(theTitle));
+ if (NS_FAILED(rv))
+ theTitle.AssignLiteral("Unknown");
+
+ rv = module->GetDescription(getter_Copies(theDescription));
+ if (NS_FAILED(rv))
+ theDescription.AssignLiteral("Unknown description");
+
+ // call the module to get the info we need
+ m_pModules->AddModule(clsId, pSupports, theTitle.get(), theDescription.get());
+
+ module->Release();
+
+ return NS_OK;
+}
+
+
+nsIImportModule *ImportModuleDesc::GetModule(bool keepLoaded)
+{
+ if (m_pModule)
+ {
+ m_pModule->AddRef();
+ return m_pModule;
+ }
+
+ nsresult rv;
+ rv = CallCreateInstance(m_cid, &m_pModule);
+ if (NS_FAILED(rv))
+ {
+ m_pModule = nullptr;
+ return nullptr;
+ }
+
+ if (keepLoaded)
+ {
+ m_pModule->AddRef();
+ return m_pModule;
+ }
+ else
+ {
+ nsIImportModule *pModule = m_pModule;
+ m_pModule = nullptr;
+ return pModule;
+ }
+}
+
+void ImportModuleDesc::ReleaseModule(void)
+{
+ if (m_pModule)
+ {
+ m_pModule->Release();
+ m_pModule = nullptr;
+ }
+}
+
+bool ImportModuleDesc::SupportsThings(const char *pThings)
+{
+ if (!pThings || !*pThings)
+ return true;
+
+ nsCString thing(pThings);
+ nsCString item;
+ int32_t idx;
+
+ while ((idx = thing.FindChar(',')) != -1)
+ {
+ item = StringHead(thing, idx);
+ item.Trim(kWhitespace);
+ ToLowerCase(item);
+ if (item.Length() && (m_supports.Find(item) == -1))
+ return false;
+ thing = Substring(thing, idx + 1);
+ }
+ thing.Trim(kWhitespace);
+ ToLowerCase(thing);
+ return thing.IsEmpty() || (m_supports.Find(thing) != -1);
+}
+
+void nsImportModuleList::ClearList(void)
+{
+ if (m_pList)
+ {
+ for (int i = 0; i < m_count; i++)
+ {
+ delete m_pList[i];
+ m_pList[i] = nullptr;
+ }
+ m_count = 0;
+ delete [] m_pList;
+ m_pList = nullptr;
+ m_alloc = 0;
+ }
+
+}
+
+void nsImportModuleList::AddModule(const nsCID& cid, const char *pSupports, const char16_t *pName, const char16_t *pDesc)
+{
+ if (!m_pList)
+ {
+ m_alloc = 10;
+ m_pList = new ImportModuleDesc *[m_alloc];
+ m_count = 0;
+ memset(m_pList, 0, sizeof(ImportModuleDesc *) * m_alloc);
+ }
+
+ if (m_count == m_alloc)
+ {
+ ImportModuleDesc **pList = new ImportModuleDesc *[m_alloc + 10];
+ memset(&(pList[m_alloc]), 0, sizeof(ImportModuleDesc *) * 10);
+ memcpy(pList, m_pList, sizeof(ImportModuleDesc *) * m_alloc);
+ for(int i = 0; i < m_count; i++)
+ delete m_pList[i];
+ delete [] m_pList;
+ m_pList = pList;
+ m_alloc += 10;
+ }
+
+ m_pList[m_count] = new ImportModuleDesc();
+ m_pList[m_count]->SetCID(cid);
+ m_pList[m_count]->SetSupports(pSupports);
+ m_pList[m_count]->SetName(pName);
+ m_pList[m_count]->SetDescription(pDesc);
+
+ m_count++;
+#ifdef IMPORT_DEBUG
+ IMPORT_LOG3("* nsImportService registered import module: %s, %s, %s\n", NS_LossyConvertUTF16toASCII(pName).get(), NS_LossyConvertUTF16toASCII(pDesc).get(), pSupports);
+#endif
+}
+