summaryrefslogtreecommitdiffstats
path: root/mailnews/import/oexpress/nsOEScanBoxes.cpp
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/oexpress/nsOEScanBoxes.cpp
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/oexpress/nsOEScanBoxes.cpp')
-rw-r--r--mailnews/import/oexpress/nsOEScanBoxes.cpp859
1 files changed, 859 insertions, 0 deletions
diff --git a/mailnews/import/oexpress/nsOEScanBoxes.cpp b/mailnews/import/oexpress/nsOEScanBoxes.cpp
new file mode 100644
index 000000000..7c30aa68d
--- /dev/null
+++ b/mailnews/import/oexpress/nsOEScanBoxes.cpp
@@ -0,0 +1,859 @@
+/* -*- Mode: C++; tab-width: 4; 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 "nsOEScanBoxes.h"
+#include "nsMsgUtils.h"
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsIImportService.h"
+#include "nsIFile.h"
+#include "nsIImportMailboxDescriptor.h"
+#include "nsOERegUtil.h"
+#include "nsOE5File.h"
+#include "nsNetUtil.h"
+#include "OEDebugLog.h"
+#include "nsIInputStream.h"
+#include "nsISeekableStream.h"
+#include "plstr.h"
+#include <windows.h>
+#include "nsIWindowsRegKey.h"
+
+#ifdef MOZILLA_INTERNAL_API
+#include "nsNativeCharsetUtils.h"
+#else
+#include "nsMsgI18N.h"
+#define NS_CopyNativeToUnicode(source, dest) \
+ nsMsgI18NConvertToUnicode(nsMsgI18NFileSystemCharset(), source, dest)
+#define NS_CopyUnicodeToNative(source, dest) \
+ nsMsgI18NConvertFromUnicode(nsMsgI18NFileSystemCharset(), source, dest)
+#endif
+
+/*
+ .nch file format???
+
+ offset 20 - long = offset to first record
+
+*/
+
+static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
+
+nsOEScanBoxes::nsOEScanBoxes()
+{
+ m_pFirst = nullptr;
+}
+
+nsOEScanBoxes::~nsOEScanBoxes()
+{
+ int i, max;
+ MailboxEntry *pEntry;
+ for (i = 0, max = m_entryArray.Length(); i < max; i++) {
+ pEntry = m_entryArray.ElementAt(i);
+ delete pEntry;
+ }
+ // Now free the unprocessed child entries (ie, those without parents for some reason).
+ for (i = 0, max = m_pendingChildArray.Length(); i < max; i++)
+ {
+ pEntry = m_pendingChildArray.ElementAt(i);
+ if (!pEntry->processed)
+ delete pEntry;
+ }
+}
+
+/*
+ 3.x & 4.x registry
+ Software/Microsoft/Outlook Express/
+
+ 5.0 registry
+ Identies - value of "Default User ID" is {GUID}
+ Identities/{GUID}/Software/Microsoft/Outlook Express/5.0/
+*/
+
+bool nsOEScanBoxes::Find50Mail(nsIFile *pWhere)
+{
+ nsAutoString userId;
+ nsresult rv = nsOERegUtil::GetDefaultUserId(userId);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ nsAutoString path(NS_LITERAL_STRING("Identities\\"));
+ path.Append(userId);
+ path.AppendLiteral("\\Software\\Microsoft\\Outlook Express\\5.0");
+
+ nsCOMPtr<nsIWindowsRegKey> key =
+ do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ rv = key->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
+ path,
+ nsIWindowsRegKey::ACCESS_QUERY_VALUE);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ nsAutoString storeRoot;
+ key->ReadStringValue(NS_LITERAL_STRING("Store Root"), storeRoot);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ nsCOMPtr<nsIFile> localWhere = do_QueryInterface(pWhere);
+ localWhere->InitWithPath(storeRoot);
+
+ nsAutoCString nativeStoreRoot;
+ NS_CopyUnicodeToNative(storeRoot, nativeStoreRoot);
+ IMPORT_LOG1("Setting native path: %s\n", nativeStoreRoot.get());
+
+ bool isDir = false;
+ rv = localWhere->IsDirectory(&isDir);
+ return isDir;
+}
+
+bool nsOEScanBoxes::FindMail(nsIFile *pWhere)
+{
+ if (Find50Mail(pWhere))
+ return true;
+
+ nsresult rv;
+ nsCOMPtr<nsIWindowsRegKey> key =
+ do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ rv = key->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
+ NS_LITERAL_STRING("Software\\Microsoft\\Outlook Express"),
+ nsIWindowsRegKey::ACCESS_QUERY_VALUE);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ nsAutoString storeRoot;
+ key->ReadStringValue(NS_LITERAL_STRING("Store Root"), storeRoot);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ nsCOMPtr<nsIFile> localWhere = do_QueryInterface(pWhere);
+ localWhere->InitWithPath(storeRoot);
+ localWhere->AppendNative(NS_LITERAL_CSTRING("Mail"));
+
+ bool isDir = false;
+ localWhere->IsDirectory(&isDir);
+
+ return isDir;
+}
+
+bool nsOEScanBoxes::GetMailboxes(nsIFile *pWhere, nsIArray **pArray)
+{
+ nsCString path;
+ pWhere->GetNativePath(path);
+ if (!path.IsEmpty()) {
+ IMPORT_LOG1("Looking for mail in: %s\n", path.get());
+ }
+ else {
+ pWhere->GetNativeLeafName(path);
+ if (!path.IsEmpty())
+ IMPORT_LOG1("Looking for mail in: %s\n", path.get());
+ else
+ IMPORT_LOG0("Unable to get info about where to look for mail\n");
+ }
+
+ nsCOMPtr <nsIFile> location;
+ pWhere->Clone(getter_AddRefs(location));
+ // 1. Look for 5.0 folders.dbx
+ // 2. Look for 3.x & 4.x folders.nch
+ // 3. Look for 5.0 *.dbx mailboxes
+ // 4. Look for 3.x & 4.x *.mbx mailboxes
+
+ bool result;
+
+ location->AppendNative(NS_LITERAL_CSTRING("folders.dbx"));
+ if (Find50MailBoxes(location)) {
+ result = GetMailboxList(pWhere, pArray);
+ }
+ else {
+ // 2. Look for 4.x mailboxes
+ pWhere->Clone(getter_AddRefs(location));
+ location->AppendNative(NS_LITERAL_CSTRING("folders.nch"));
+
+ if (FindMailBoxes(location)) {
+ result = GetMailboxList(pWhere, pArray);
+ }
+ else {
+ // 3 & 4, look for the specific mailbox files.
+ pWhere->Clone(getter_AddRefs(location));
+ ScanMailboxDir(location);
+ result = GetMailboxList(pWhere, pArray);
+ }
+ }
+
+ return result;
+}
+
+
+
+void nsOEScanBoxes::Reset(void)
+{
+ int max = m_entryArray.Length();
+ for (int i = 0; i < max; i++) {
+ MailboxEntry *pEntry = m_entryArray.ElementAt(i);
+ delete pEntry;
+ }
+ m_entryArray.Clear();
+ m_pFirst = nullptr;
+}
+
+
+bool nsOEScanBoxes::FindMailBoxes(nsIFile* descFile)
+{
+ Reset();
+
+ nsresult rv;
+ bool isFile = false;
+
+ rv = descFile->IsFile(&isFile);
+ if (NS_FAILED(rv) || !isFile)
+ return false;
+
+ nsCOMPtr <nsIInputStream> descInputStream;
+ rv = NS_NewLocalFileInputStream(getter_AddRefs(descInputStream), descFile);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ IMPORT_LOG0("Reading the folders.nch file\n");
+
+ uint32_t curRec;
+ if (!ReadLong(descInputStream, curRec, 20)) {
+ return false;
+ }
+
+ // Now for each record
+ bool done = false;
+ uint32_t equal;
+ uint32_t size;
+ uint32_t previous;
+ uint32_t next;
+ MailboxEntry * pEntry;
+ bool failed;
+
+ while (!done) {
+ if (!ReadLong(descInputStream, equal, curRec)) return false;
+ if (curRec != equal) {
+ IMPORT_LOG1("Record start invalid: %ld\n", curRec);
+ break;
+ }
+ if (!ReadLong(descInputStream, size, curRec + 4)) return false;
+ if (!ReadLong(descInputStream, previous, curRec + 8)) return false;
+ if (!ReadLong(descInputStream, next, curRec + 12)) return false;
+ failed = false;
+ pEntry = new MailboxEntry;
+ if (!ReadLong(descInputStream, pEntry->index, curRec + 16)) failed = true;
+ if (!ReadString(descInputStream, pEntry->mailName, curRec + 20)) failed = true;
+ if (!ReadString(descInputStream, pEntry->fileName, curRec + 279)) failed = true;
+ if (!ReadLong(descInputStream, pEntry->parent, curRec + 539)) failed = true;
+ if (!ReadLong(descInputStream, pEntry->child, curRec + 543)) failed = true;
+ if (!ReadLong(descInputStream, pEntry->sibling, curRec + 547)) failed = true;
+ if (!ReadLong(descInputStream, pEntry->type, curRec + 551)) failed = true;
+ if (failed) {
+ delete pEntry;
+ return false;
+ }
+
+ #ifdef _TRACE_MAILBOX_ENTRIES
+ IMPORT_LOG0("------------\n");
+ IMPORT_LOG2(" Offset: %lx, index: %ld\n", curRec, pEntry->index);
+ IMPORT_LOG2(" previous: %lx, next: %lx\n", previous, next);
+ IMPORT_LOG2(" Name: %S, File: %s\n", (char16_t *) pEntry->mailName, (const char *) pEntry->fileName);
+ IMPORT_LOG3(" Parent: %ld, Child: %ld, Sibling: %ld\n", pEntry->parent, pEntry->child, pEntry->sibling);
+ #endif
+
+ if (!StringEndsWith(pEntry->fileName, NS_LITERAL_CSTRING(".mbx")))
+ pEntry->fileName.Append(".mbx");
+
+ m_entryArray.AppendElement(pEntry);
+
+ curRec = next;
+ if (!next)
+ done = true;
+ }
+
+ MailboxEntry *pZero = GetIndexEntry(0);
+ if (pZero)
+ m_pFirst = GetIndexEntry(pZero->child);
+
+ IMPORT_LOG1("Read the folders.nch file, found %ld mailboxes\n", (long) m_entryArray.Length());
+
+ return true;
+}
+
+bool nsOEScanBoxes::Find50MailBoxes(nsIFile* descFile)
+{
+ Reset();
+
+ nsresult rv;
+ bool isFile = false;
+
+ rv = descFile->IsFile(&isFile);
+ if (NS_FAILED(rv) || !isFile)
+ return false;
+
+ nsCOMPtr <nsIInputStream> descInputStream;
+ rv = NS_NewLocalFileInputStream(getter_AddRefs(descInputStream), descFile);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ IMPORT_LOG0("Reading the folders.dbx file\n");
+
+ uint32_t *pIndex;
+ uint32_t indexSize = 0;
+ if (!nsOE5File::ReadIndex(descInputStream, &pIndex, &indexSize)) {
+ IMPORT_LOG0("*** NOT USING FOLDERS.DBX!!!\n");
+ return false;
+ }
+
+ uint32_t marker;
+ uint32_t size;
+ char *pBytes;
+ uint32_t cntRead;
+ int32_t recordId;
+ int32_t strOffset;
+
+ uint8_t tag;
+ uint32_t data;
+ int32_t dataOffset;
+
+ uint32_t id;
+ uint32_t parent;
+ uint32_t numMessages;
+ char * pFileName;
+ char * pDataSource;
+
+ MailboxEntry * pEntry;
+ MailboxEntry * pLastEntry = nullptr;
+
+ uint32_t localStoreId = 0;
+
+ for (uint32_t i = 0; i < indexSize; i++) {
+ if (!ReadLong(descInputStream, marker, pIndex[i])) continue;
+ if (marker != pIndex[i]) continue;
+ if (!ReadLong(descInputStream, size, pIndex[i] + 4)) continue;
+ size += 4;
+ pBytes = new char[size];
+ rv = descInputStream->Read(pBytes, size, &cntRead);
+ if (NS_FAILED(rv) || ((uint32_t)cntRead != size)) {
+ delete [] pBytes;
+ continue;
+ }
+ recordId = pBytes[2];
+ strOffset = (recordId * 4) + 4;
+ if (recordId == 4)
+ strOffset += 4;
+
+ id = 0;
+ parent = 0;
+ numMessages = 0;
+ pFileName = nullptr;
+ pDataSource = nullptr;
+ dataOffset = 4;
+ while (dataOffset < strOffset) {
+ tag = (uint8_t) pBytes[dataOffset];
+
+ data = 0; // make sure all bytes are 0 before copying 3 bytes over.
+ memcpy(&data, &(pBytes[dataOffset + 1]), 3);
+ switch(tag) {
+ case 0x80: // id record
+ id = data;
+ break;
+ case 0x81: // parent id
+ parent = data;
+ break;
+ case 0x87: // number of messages in this mailbox
+ numMessages = data;
+ break;
+ case 0x03: // file name for this mailbox
+ if (((uint32_t)strOffset + data) < size)
+ pFileName = (char *)(pBytes + strOffset + data);
+ break;
+ case 0x05: // data source for this record (this is not a mailbox!)
+ if (((uint32_t)strOffset + data) < size)
+ pDataSource = (char *) (pBytes + strOffset + data);
+ break;
+ }
+ dataOffset += 4;
+ }
+
+ // now build an entry if necessary!
+ if (pDataSource) {
+ if (!PL_strcasecmp(pDataSource, "LocalStore"))
+ {
+ localStoreId = id;
+ // See if we have any child folders that need to be added/processed for this top level parent.
+ ProcessPendingChildEntries(localStoreId, localStoreId, m_pendingChildArray);
+ // Clean up the pending list.
+ RemoveProcessedChildEntries();
+ }
+ }
+ else if (id && localStoreId && parent) {
+ // veryify that this mailbox is in the local store
+ data = parent;
+ while (data && (data != localStoreId)) {
+ pEntry = GetIndexEntry(data);
+ if (pEntry)
+ data = pEntry->parent;
+ else
+ data = 0;
+ }
+ if (data == localStoreId) {
+ // Create an entry for this bugger
+ pEntry = NewMailboxEntry(id, parent, (const char *) (pBytes + strOffset), pFileName);
+ if (pEntry)
+ {
+ AddChildEntry(pEntry, localStoreId);
+ pEntry->processed = true;
+ // See if we have any child folders that need to be added/processed.
+ ProcessPendingChildEntries(id, localStoreId, m_pendingChildArray);
+ // Clean up the pending list.
+ RemoveProcessedChildEntries();
+ }
+ }
+ else
+ {
+ // Put this folder into child array and process it when its parent shows up.
+ pEntry = NewMailboxEntry(id, parent, (const char *) (pBytes + strOffset), pFileName);
+ if (pEntry)
+ m_pendingChildArray.AppendElement(pEntry);
+ }
+ }
+ else if (pFileName)
+ {
+ // Put this folder into child array and process it when its parent shows up.
+ // For some reason, it's likely that child folders come before their parents.
+ pEntry = NewMailboxEntry(id, parent, (const char *) (pBytes + strOffset), pFileName);
+ if (pEntry)
+ m_pendingChildArray.AppendElement(pEntry);
+ }
+
+ delete [] pBytes;
+ }
+
+
+ delete [] pIndex;
+
+ return m_entryArray.Length();
+}
+
+nsOEScanBoxes::MailboxEntry *nsOEScanBoxes::NewMailboxEntry(uint32_t id, uint32_t parent, const char *prettyName, char *pFileName)
+{
+ MailboxEntry *pEntry = new MailboxEntry();
+ if (!pEntry)
+ return nullptr;
+
+ pEntry->index = id;
+ pEntry->parent = parent;
+ pEntry->child = 0;
+ pEntry->type = 0;
+ pEntry->sibling = -1;
+ pEntry->processed = false;
+ NS_CopyNativeToUnicode(nsDependentCString(prettyName), pEntry->mailName);
+ if (pFileName)
+ pEntry->fileName = pFileName;
+ return pEntry;
+}
+
+void nsOEScanBoxes::ProcessPendingChildEntries(uint32_t parent, uint32_t rootIndex, nsTArray<MailboxEntry*> &childArray)
+{
+ int32_t i, max;
+ MailboxEntry *pEntry;
+ for (i = 0, max = childArray.Length(); i < max; i++)
+ {
+ pEntry = childArray.ElementAt(i);
+ if ((!pEntry->processed) && (pEntry->parent == parent))
+ {
+ AddChildEntry(pEntry, rootIndex);
+ pEntry->processed = true; // indicate it's been processed.
+ // See if there are unprocessed child folders for this child in the
+ // array as well (ie, both child and grand-child are on the list).
+ ProcessPendingChildEntries(pEntry->index, rootIndex, childArray);
+ }
+ }
+}
+
+void nsOEScanBoxes::RemoveProcessedChildEntries()
+{
+ // Remove already processed entries from the pending list. Note that these entries are also
+ // on 'm_entryArray' list so we don't want to deallocate the space for the entries now.
+ MailboxEntry * pEntry;
+ int32_t i;
+ for (i = m_pendingChildArray.Length()-1; i >= 0; i--)
+ {
+ pEntry = m_pendingChildArray.ElementAt(i);
+ if (pEntry->processed)
+ m_pendingChildArray.RemoveElementAt(i);
+ }
+}
+
+void nsOEScanBoxes::AddChildEntry(MailboxEntry *pEntry, uint32_t rootIndex)
+{
+ if (!m_pFirst) {
+ if (pEntry->parent == rootIndex) {
+ m_pFirst = pEntry;
+ m_entryArray.AppendElement(pEntry);
+ }
+ else {
+ delete pEntry;
+ }
+ return;
+ }
+
+ MailboxEntry * pParent = nullptr;
+ MailboxEntry * pSibling = nullptr;
+ if (pEntry->parent == rootIndex) {
+ pSibling = m_pFirst;
+ }
+ else {
+ pParent = GetIndexEntry(pEntry->parent);
+ }
+
+ if (!pParent && !pSibling) {
+ delete pEntry;
+ return;
+ }
+
+ if (pParent && (pParent->child == 0)) {
+ pParent->child = pEntry->index;
+ m_entryArray.AppendElement(pEntry);
+ return;
+ }
+
+ if (!pSibling)
+ pSibling = GetIndexEntry(pParent->child);
+
+ while (pSibling && (pSibling->sibling != -1)) {
+ pSibling = GetIndexEntry(pSibling->sibling);
+ }
+
+ if (!pSibling) {
+ delete pEntry;
+ return;
+ }
+
+ pSibling->sibling = pEntry->index;
+ m_entryArray.AppendElement(pEntry);
+}
+
+bool nsOEScanBoxes::Scan50MailboxDir(nsIFile * srcDir)
+{
+ Reset();
+
+ MailboxEntry *pEntry;
+ int32_t index = 1;
+ char *pLeaf;
+
+ bool hasMore;
+ nsCOMPtr<nsISimpleEnumerator> directoryEnumerator;
+ nsresult rv = srcDir->GetDirectoryEntries(getter_AddRefs(directoryEnumerator));
+ NS_ENSURE_SUCCESS(rv, false);
+
+ directoryEnumerator->HasMoreElements(&hasMore);
+ bool isFile;
+ nsCOMPtr<nsIFile> entry;
+ nsCString fName;
+
+ while (hasMore && NS_SUCCEEDED(rv))
+ {
+ nsCOMPtr<nsISupports> aSupport;
+ rv = directoryEnumerator->GetNext(getter_AddRefs(aSupport));
+ nsCOMPtr<nsIFile> entry(do_QueryInterface(aSupport, &rv));
+ directoryEnumerator->HasMoreElements(&hasMore);
+
+ isFile = false;
+ rv = entry->IsFile(&isFile);
+ if (NS_SUCCEEDED(rv) && isFile) {
+ pLeaf = nullptr;
+ rv = entry->GetNativeLeafName(fName);
+ if (NS_SUCCEEDED(rv) &&
+ (StringEndsWith(fName, NS_LITERAL_CSTRING(".dbx")))) {
+ // This is a *.dbx file in the mail directory
+ if (nsOE5File::IsLocalMailFile(entry)) {
+ pEntry = new MailboxEntry;
+ pEntry->index = index;
+ index++;
+ pEntry->parent = 0;
+ pEntry->child = 0;
+ pEntry->sibling = index;
+ pEntry->type = -1;
+ fName.SetLength(fName.Length() - 4);
+ pEntry->fileName = fName.get();
+ NS_CopyNativeToUnicode(fName, pEntry->mailName);
+ m_entryArray.AppendElement(pEntry);
+ }
+ }
+ }
+ }
+
+ if (m_entryArray.Length() > 0) {
+ pEntry = m_entryArray.ElementAt(m_entryArray.Length() - 1);
+ pEntry->sibling = -1;
+ return true;
+ }
+
+ return false;
+}
+
+void nsOEScanBoxes::ScanMailboxDir(nsIFile * srcDir)
+{
+ if (Scan50MailboxDir(srcDir))
+ return;
+
+ Reset();
+
+ MailboxEntry * pEntry;
+ int32_t index = 1;
+ nsAutoCString pLeaf;
+ uint32_t sLen;
+
+ bool hasMore;
+ nsCOMPtr<nsISimpleEnumerator> directoryEnumerator;
+ nsresult rv = srcDir->GetDirectoryEntries(getter_AddRefs(directoryEnumerator));
+ NS_ENSURE_SUCCESS_VOID(rv);
+
+ directoryEnumerator->HasMoreElements(&hasMore);
+ bool isFile;
+ nsCOMPtr<nsIFile> entry;
+ nsCString fName;
+ nsCString ext;
+ nsCString name;
+
+ while (hasMore && NS_SUCCEEDED(rv))
+ {
+ nsCOMPtr<nsISupports> aSupport;
+ rv = directoryEnumerator->GetNext(getter_AddRefs(aSupport));
+ nsCOMPtr<nsIFile> entry(do_QueryInterface(aSupport, &rv));
+ directoryEnumerator->HasMoreElements(&hasMore);
+
+ isFile = false;
+ rv = entry->IsFile(&isFile);
+ if (NS_SUCCEEDED(rv) && isFile)
+ {
+ rv = entry->GetNativeLeafName(pLeaf);
+ if (NS_SUCCEEDED(rv) && !pLeaf.IsEmpty() &&
+ ((sLen = pLeaf.Length()) > 4) &&
+ (!PL_strcasecmp(pLeaf.get() + sLen - 3, "mbx")))
+ {
+ // This is a *.mbx file in the mail directory
+ pEntry = new MailboxEntry;
+ pEntry->index = index;
+ index++;
+ pEntry->parent = 0;
+ pEntry->child = 0;
+ pEntry->sibling = index;
+ pEntry->type = -1;
+ pEntry->fileName = pLeaf;
+ pLeaf.SetLength(sLen - 4);
+ NS_CopyNativeToUnicode(pLeaf, pEntry->mailName);
+ m_entryArray.AppendElement(pEntry);
+ }
+ }
+ }
+
+ if (m_entryArray.Length() > 0) {
+ pEntry = m_entryArray.ElementAt(m_entryArray.Length() - 1);
+ pEntry->sibling = -1;
+ }
+}
+
+uint32_t nsOEScanBoxes::CountMailboxes(MailboxEntry *pBox)
+{
+ if (pBox == nullptr) {
+ if (m_pFirst != nullptr)
+ pBox = m_pFirst;
+ else {
+ if (m_entryArray.Length() > 0)
+ pBox = m_entryArray.ElementAt(0);
+ }
+ }
+ uint32_t count = 0;
+
+ MailboxEntry * pChild;
+ while (pBox) {
+ count++;
+ if (pBox->child) {
+ pChild = GetIndexEntry(pBox->child);
+ if (pChild != nullptr)
+ count += CountMailboxes(pChild);
+ }
+ if (pBox->sibling != -1) {
+ pBox = GetIndexEntry(pBox->sibling);
+ }
+ else
+ pBox = nullptr;
+ }
+
+ return count;
+}
+
+bool nsOEScanBoxes::GetMailboxList(nsIFile * root, nsIArray **pArray)
+{
+ nsresult rv;
+ nsCOMPtr<nsIMutableArray> array(do_CreateInstance(NS_ARRAY_CONTRACTID, &rv));
+ if (NS_FAILED(rv)) {
+ IMPORT_LOG0("FAILED to allocate the nsIArray\n");
+ return false;
+ }
+
+ BuildMailboxList(nullptr, root, 1, array);
+ array.forget(pArray);
+
+ return true;
+}
+
+void nsOEScanBoxes::BuildMailboxList(MailboxEntry *pBox, nsIFile * root, int32_t depth, nsIMutableArray *pArray)
+{
+ if (pBox == nullptr) {
+ if (m_pFirst != nullptr) {
+ pBox = m_pFirst;
+
+ IMPORT_LOG0("Assigning start of mailbox list to m_pFirst\n");
+ }
+ else {
+ if (m_entryArray.Length() > 0) {
+ pBox = m_entryArray.ElementAt(0);
+
+ IMPORT_LOG0("Assigning start of mailbox list to entry at index 0\n");
+ }
+ }
+
+ if (pBox == nullptr) {
+ IMPORT_LOG0("ERROR ASSIGNING STARTING MAILBOX\n");
+ }
+
+ }
+
+ nsresult rv;
+ nsCOMPtr<nsIFile> file;
+ MailboxEntry *pChild;
+ nsIImportMailboxDescriptor *pID;
+ nsISupports *pInterface;
+ int64_t size;
+
+ nsCOMPtr<nsIImportService> impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS_VOID(rv);
+
+ while (pBox) {
+ rv = impSvc->CreateNewMailboxDescriptor(&pID);
+ if (NS_SUCCEEDED(rv)) {
+ pID->SetDepth(depth);
+ pID->SetIdentifier(pBox->index);
+ pID->SetDisplayName((char16_t *)pBox->mailName.get());
+ if (!pBox->fileName.IsEmpty()) {
+ pID->GetFile(getter_AddRefs(file));
+ file->InitWithFile(root);
+ file->AppendNative(pBox->fileName);
+ size = 0;
+ file->GetFileSize(&size);
+ pID->SetSize(size);
+ }
+ rv = pID->QueryInterface(kISupportsIID, (void **) &pInterface);
+ pArray->AppendElement(pInterface, false);
+ pInterface->Release();
+ pID->Release();
+ }
+
+ if (pBox->child) {
+ pChild = GetIndexEntry(pBox->child);
+ if (pChild != nullptr)
+ BuildMailboxList(pChild, root, depth + 1, pArray);
+ }
+ if (pBox->sibling != -1) {
+ pBox = GetIndexEntry(pBox->sibling);
+ }
+ else
+ pBox = nullptr;
+ }
+
+}
+
+nsOEScanBoxes::MailboxEntry * nsOEScanBoxes::GetIndexEntry(uint32_t index)
+{
+ int32_t max = m_entryArray.Length();
+ for (int32_t i = 0; i < max; i++) {
+ MailboxEntry *pEntry = m_entryArray.ElementAt(i);
+ if (pEntry->index == index)
+ return pEntry;
+ }
+
+ return nullptr;
+}
+
+
+// -------------------------------------------------------
+// File utility routines
+// -------------------------------------------------------
+
+bool nsOEScanBoxes::ReadLong(nsIInputStream * stream, int32_t& val, uint32_t offset)
+{
+ nsresult rv;
+ nsCOMPtr <nsISeekableStream> seekStream = do_QueryInterface(stream, &rv);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ rv = seekStream->Seek(nsISeekableStream::NS_SEEK_SET, offset);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ uint32_t cntRead;
+ char * pReadTo = (char *)&val;
+ rv = stream->Read(pReadTo, sizeof(val), &cntRead);
+
+ return NS_SUCCEEDED(rv) && cntRead == sizeof(val);
+}
+
+bool nsOEScanBoxes::ReadLong(nsIInputStream * stream, uint32_t& val, uint32_t offset)
+{
+ nsresult rv;
+ nsCOMPtr <nsISeekableStream> seekStream = do_QueryInterface(stream, &rv);
+ NS_ENSURE_SUCCESS(rv, false);
+ rv = seekStream->Seek(nsISeekableStream::NS_SEEK_SET, offset);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ uint32_t cntRead;
+ char * pReadTo = (char *)&val;
+ rv = stream->Read(pReadTo, sizeof(val), &cntRead);
+ if (NS_FAILED(rv) || (cntRead != sizeof(val)))
+ return false;
+
+ return true;
+}
+
+// It appears as though the strings for file name and mailbox
+// name are at least 254 chars - verified - they are probably 255
+// but why bother going that far! If a file name is that long then
+// the heck with it.
+#define kOutlookExpressStringLength 252
+bool nsOEScanBoxes::ReadString(nsIInputStream * stream, nsString& str, uint32_t offset)
+{
+ nsresult rv;
+ nsCOMPtr<nsISeekableStream> seekStream = do_QueryInterface(stream, &rv);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ rv = seekStream->Seek(nsISeekableStream::NS_SEEK_SET, offset);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ uint32_t cntRead;
+ char buffer[kOutlookExpressStringLength];
+ char *pReadTo = buffer;
+ rv = stream->Read(pReadTo, kOutlookExpressStringLength, &cntRead);
+ if (NS_FAILED(rv) || (cntRead != kOutlookExpressStringLength))
+ return false;
+
+ buffer[kOutlookExpressStringLength - 1] = 0;
+ str.AssignASCII(buffer);
+ return true;
+}
+
+bool nsOEScanBoxes::ReadString(nsIInputStream * stream, nsCString& str, uint32_t offset)
+{
+ nsresult rv;
+ nsCOMPtr<nsISeekableStream> seekStream = do_QueryInterface(stream, &rv);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ rv = seekStream->Seek(nsISeekableStream::NS_SEEK_SET, offset);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ uint32_t cntRead;
+ char buffer[kOutlookExpressStringLength];
+ char *pReadTo = buffer;
+ rv = stream->Read(pReadTo, kOutlookExpressStringLength, &cntRead);
+ if (NS_FAILED(rv) || (cntRead != kOutlookExpressStringLength))
+ return false;
+
+ buffer[kOutlookExpressStringLength - 1] = 0;
+ str = buffer;
+ return true;
+}