mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-20 23:37:33 +09:00
859 lines
24 KiB
C++
859 lines
24 KiB
C++
/* -*- 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;
|
|
}
|