mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-27 10:57:34 +09:00
Issue #1258 - Part 1: Import mailnews, ldap, and mork from comm-esr52.9.1
This commit is contained in:
parent
23e0d82436
commit
e400f4130a
1564 changed files with 510348 additions and 0 deletions
20
mailnews/import/oexpress/OEDebugLog.h
Normal file
20
mailnews/import/oexpress/OEDebugLog.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#ifndef OEDebugLog_h___
|
||||
#define OEDebugLog_h___
|
||||
|
||||
// Use MOZ_LOG for logging.
|
||||
#include "mozilla/Logging.h"
|
||||
extern PRLogModuleInfo *OELOGMODULE; // Logging module
|
||||
|
||||
#define IMPORT_LOG0(x) MOZ_LOG(OELOGMODULE, mozilla::LogLevel::Debug, (x))
|
||||
#define IMPORT_LOG1(x, y) MOZ_LOG(OELOGMODULE, mozilla::LogLevel::Debug, (x, y))
|
||||
#define IMPORT_LOG2(x, y, z) MOZ_LOG(OELOGMODULE, mozilla::LogLevel::Debug, (x, y, z))
|
||||
#define IMPORT_LOG3(a, b, c, d) MOZ_LOG(OELOGMODULE, mozilla::LogLevel::Debug, (a, b, c, d))
|
||||
|
||||
|
||||
|
||||
#endif /* OEDebugLog_h___ */
|
||||
1132
mailnews/import/oexpress/WabObject.cpp
Normal file
1132
mailnews/import/oexpress/WabObject.cpp
Normal file
File diff suppressed because it is too large
Load diff
64
mailnews/import/oexpress/WabObject.h
Normal file
64
mailnews/import/oexpress/WabObject.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#ifndef WabObject_h___
|
||||
#define WabObject_h___
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsIFile.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <wab.h>
|
||||
|
||||
|
||||
class CWabIterator {
|
||||
public:
|
||||
virtual nsresult EnumUser(const char16_t *pName, LPENTRYID pEid, ULONG cbEid) = 0;
|
||||
virtual nsresult EnumList(const char16_t *pName, LPENTRYID pEid, ULONG cbEid, LPMAPITABLE lpTable) = 0;
|
||||
};
|
||||
|
||||
|
||||
class CWAB
|
||||
{
|
||||
public:
|
||||
CWAB(nsIFile *fileName);
|
||||
~CWAB();
|
||||
|
||||
bool Loaded(void) { return m_bInitialized;}
|
||||
|
||||
HRESULT IterateWABContents(CWabIterator *pIter, int *pDone);
|
||||
|
||||
// Methods for User entries
|
||||
LPDISTLIST GetDistList(ULONG cbEid, LPENTRYID pEid);
|
||||
void ReleaseDistList(LPDISTLIST pList) { if (pList) pList->Release();}
|
||||
LPMAILUSER GetUser(ULONG cbEid, LPENTRYID pEid);
|
||||
void ReleaseUser(LPMAILUSER pUser) { if (pUser) pUser->Release();}
|
||||
LPSPropValue GetUserProperty(LPMAILUSER pUser, ULONG tag);
|
||||
LPSPropValue GetListProperty(LPDISTLIST pList, ULONG tag);
|
||||
void FreeProperty(LPSPropValue pVal) { if (pVal) m_lpWABObject->FreeBuffer(pVal);}
|
||||
void GetValueString(LPSPropValue pVal, nsString& val);
|
||||
void GetValueTime(LPSPropValue pVal, PRTime& val);
|
||||
|
||||
void CStrToUnicode(const char *pStr, nsString& result);
|
||||
|
||||
// Utility stuff used by iterate
|
||||
void FreeProws(LPSRowSet prows);
|
||||
|
||||
bool IsAvailable();
|
||||
|
||||
private:
|
||||
char16_t * m_pUniBuff;
|
||||
int m_uniBuffLen;
|
||||
bool m_bInitialized;
|
||||
HINSTANCE m_hinstWAB;
|
||||
LPWABOPEN m_lpfnWABOpen;
|
||||
LPADRBOOK m_lpAdrBook;
|
||||
LPWABOBJECT m_lpWABObject;
|
||||
};
|
||||
|
||||
#endif // WABOBJECT_INCLUDED
|
||||
|
||||
|
||||
19
mailnews/import/oexpress/moz.build
Normal file
19
mailnews/import/oexpress/moz.build
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# 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/.
|
||||
|
||||
SOURCES += [
|
||||
'nsOE5File.cpp',
|
||||
'nsOEAddressIterator.cpp',
|
||||
'nsOEImport.cpp',
|
||||
'nsOEMailbox.cpp',
|
||||
'nsOERegUtil.cpp',
|
||||
'nsOEScanBoxes.cpp',
|
||||
'nsOESettings.cpp',
|
||||
'nsOEStringBundle.cpp',
|
||||
'WabObject.cpp',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'import'
|
||||
|
||||
631
mailnews/import/oexpress/nsOE5File.cpp
Normal file
631
mailnews/import/oexpress/nsOE5File.cpp
Normal file
|
|
@ -0,0 +1,631 @@
|
|||
/* -*- 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 "nsOE5File.h"
|
||||
#include "OEDebugLog.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "msgCore.h"
|
||||
#include "prprf.h"
|
||||
#include "nsMsgLocalFolderHdrs.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIMsgPluggableStore.h"
|
||||
#include "nsIMsgHdr.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsISeekableStream.h"
|
||||
#include "nsMsgMessageFlags.h"
|
||||
#include <windows.h>
|
||||
|
||||
#define kIndexGrowBy 100
|
||||
#define kSignatureSize 12
|
||||
#define kDontSeek 0xFFFFFFFF
|
||||
#define MARKED 0x20 // 4
|
||||
#define READ 0x80 // 1
|
||||
#define HASATTACHMENT 0x4000 // 268435456 10000000h
|
||||
#define ISANSWERED 0x80000 // 2
|
||||
#define ISFORWARDED 0x100000 // 4096
|
||||
#define ISWATCHED 0x400000 // 256
|
||||
#define ISIGNORED 0x800000 // 262144
|
||||
#define XLATFLAGS(s) (((MARKED & s) ? nsMsgMessageFlags::Marked : 0) | \
|
||||
((READ & s) ? nsMsgMessageFlags::Read : 0) | \
|
||||
((HASATTACHMENT & s) ? nsMsgMessageFlags::Attachment : 0) | \
|
||||
((ISANSWERED & s) ? nsMsgMessageFlags::Replied : 0) | \
|
||||
((ISFORWARDED & s) ? nsMsgMessageFlags::Forwarded : 0) | \
|
||||
((ISWATCHED & s) ? nsMsgMessageFlags::Watched : 0) | \
|
||||
((ISIGNORED & s) ? nsMsgMessageFlags::Ignored : 0))
|
||||
|
||||
static char *gSig =
|
||||
"\xCF\xAD\x12\xFE\xC5\xFD\x74\x6F\x66\xE3\xD1\x11";
|
||||
|
||||
// copied from nsprpub/pr/src/{io/prfile.c | md/windows/w95io.c} :
|
||||
// PR_FileTimeToPRTime and _PR_FileTimeToPRTime
|
||||
void nsOE5File::FileTimeToPRTime(const FILETIME *filetime, PRTime *prtm)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
const PRTime _pr_filetime_offset = 116444736000000000LL;
|
||||
#else
|
||||
const PRTime _pr_filetime_offset = 116444736000000000i64;
|
||||
#endif
|
||||
|
||||
PR_ASSERT(sizeof(FILETIME) == sizeof(PRTime));
|
||||
::CopyMemory(prtm, filetime, sizeof(PRTime));
|
||||
#ifdef __GNUC__
|
||||
*prtm = (*prtm - _pr_filetime_offset) / 10LL;
|
||||
#else
|
||||
*prtm = (*prtm - _pr_filetime_offset) / 10i64;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool nsOE5File::VerifyLocalMailFile(nsIFile *pFile)
|
||||
{
|
||||
char sig[kSignatureSize];
|
||||
|
||||
nsCOMPtr <nsIInputStream> inputStream;
|
||||
|
||||
if (NS_FAILED(NS_NewLocalFileInputStream(getter_AddRefs(inputStream), pFile)))
|
||||
return false;
|
||||
|
||||
if (!ReadBytes(inputStream, sig, 0, kSignatureSize))
|
||||
return false;
|
||||
|
||||
bool result = true;
|
||||
|
||||
for (int i = 0; (i < kSignatureSize) && result; i++) {
|
||||
if (sig[i] != gSig[i])
|
||||
result = false;
|
||||
}
|
||||
|
||||
char storeName[14];
|
||||
if (!ReadBytes(inputStream, storeName, 0x24C1, 12))
|
||||
result = false;
|
||||
|
||||
storeName[12] = 0;
|
||||
|
||||
if (PL_strcasecmp("LocalStore", storeName))
|
||||
result = false;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool nsOE5File::IsLocalMailFile(nsIFile *pFile)
|
||||
{
|
||||
nsresult rv;
|
||||
bool isFile = false;
|
||||
|
||||
rv = pFile->IsFile(&isFile);
|
||||
if (NS_FAILED(rv) || !isFile)
|
||||
return false;
|
||||
|
||||
bool result = VerifyLocalMailFile(pFile);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool nsOE5File::ReadIndex(nsIInputStream *pInputStream, uint32_t **ppIndex, uint32_t *pSize)
|
||||
{
|
||||
*ppIndex = nullptr;
|
||||
*pSize = 0;
|
||||
|
||||
char signature[4];
|
||||
if (!ReadBytes(pInputStream, signature, 0, 4))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (signature[i] != gSig[i]) {
|
||||
IMPORT_LOG0("*** Outlook 5.0 dbx file signature doesn't match\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t offset = 0x00e4;
|
||||
uint32_t indexStart = 0;
|
||||
if (!ReadBytes(pInputStream, &indexStart, offset, 4)) {
|
||||
IMPORT_LOG0("*** Unable to read offset to index start\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
PRUint32Array array;
|
||||
array.count = 0;
|
||||
array.alloc = kIndexGrowBy;
|
||||
array.pIndex = new uint32_t[kIndexGrowBy];
|
||||
|
||||
uint32_t next = ReadMsgIndex(pInputStream, indexStart, &array);
|
||||
while (next) {
|
||||
next = ReadMsgIndex(pInputStream, next, &array);
|
||||
}
|
||||
|
||||
if (array.count) {
|
||||
*pSize = array.count;
|
||||
*ppIndex = array.pIndex;
|
||||
return true;
|
||||
}
|
||||
|
||||
delete [] array.pIndex;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
uint32_t nsOE5File::ReadMsgIndex(nsIInputStream *pInputStream, uint32_t offset, PRUint32Array *pArray)
|
||||
{
|
||||
// Record is:
|
||||
// 4 byte marker
|
||||
// 4 byte unknown
|
||||
// 4 byte nextSubIndex
|
||||
// 4 byte (parentIndex?)
|
||||
// 2 bytes unknown
|
||||
// 1 byte length - # of entries in this record
|
||||
// 1 byte unknown
|
||||
// 4 byte unknown
|
||||
// length records consisting of 3 longs
|
||||
// 1 - pointer to record
|
||||
// 2 - child index pointer
|
||||
// 3 - number of records in child
|
||||
|
||||
uint32_t marker;
|
||||
|
||||
if (!ReadBytes(pInputStream, &marker, offset, 4))
|
||||
return 0;
|
||||
|
||||
if (marker != offset)
|
||||
return 0;
|
||||
|
||||
|
||||
uint32_t vals[3];
|
||||
|
||||
if (!ReadBytes(pInputStream, vals, offset + 4, 12))
|
||||
return 0;
|
||||
|
||||
|
||||
uint8_t len[4];
|
||||
if (!ReadBytes(pInputStream, len, offset + 16, 4))
|
||||
return 0;
|
||||
|
||||
|
||||
|
||||
uint32_t cnt = (uint32_t) len[1];
|
||||
cnt *= 3;
|
||||
uint32_t *pData = new uint32_t[cnt];
|
||||
|
||||
if (!ReadBytes(pInputStream, pData, offset + 24, cnt * 4)) {
|
||||
delete [] pData;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t next;
|
||||
uint32_t indexOffset;
|
||||
uint32_t * pRecord = pData;
|
||||
uint32_t * pNewIndex;
|
||||
|
||||
for (uint8_t i = 0; i < (uint8_t)len[1]; i++, pRecord += 3) {
|
||||
indexOffset = pRecord[0];
|
||||
|
||||
if (pArray->count >= pArray->alloc) {
|
||||
pNewIndex = new uint32_t[ pArray->alloc + kIndexGrowBy];
|
||||
memcpy(pNewIndex, pArray->pIndex, (pArray->alloc * 4));
|
||||
(pArray->alloc) += kIndexGrowBy;
|
||||
delete [] pArray->pIndex;
|
||||
pArray->pIndex = pNewIndex;
|
||||
}
|
||||
|
||||
/*
|
||||
We could do some checking here if we wanted -
|
||||
make sure the index is within the file,
|
||||
make sure there isn't a duplicate index, etc.
|
||||
*/
|
||||
|
||||
pArray->pIndex[pArray->count] = indexOffset;
|
||||
(pArray->count)++;
|
||||
|
||||
|
||||
|
||||
next = pRecord[1];
|
||||
if (next)
|
||||
while ((next = ReadMsgIndex(pInputStream, next, pArray)) != 0);
|
||||
}
|
||||
delete [] pData;
|
||||
|
||||
// return the pointer to the next subIndex
|
||||
return vals[1];
|
||||
}
|
||||
|
||||
bool nsOE5File::IsFromLine(char *pLine, uint32_t len)
|
||||
{
|
||||
return (len > 5 && (pLine[0] == 'F') && (pLine[1] == 'r') && (pLine[2] == 'o') && (pLine[3] == 'm') && (pLine[4] == ' '));
|
||||
}
|
||||
|
||||
// Anything over 16K will be assumed BAD, BAD, BAD!
|
||||
#define kMailboxBufferSize 0x4000
|
||||
#define kMaxAttrCount 0x0030
|
||||
const char *nsOE5File::m_pFromLineSep = "From - Mon Jan 1 00:00:00 1965\x0D\x0A";
|
||||
|
||||
nsresult nsOE5File::ImportMailbox(uint32_t *pBytesDone, bool *pAbort,
|
||||
nsString& name, nsIFile *inFile,
|
||||
nsIMsgFolder *dstFolder, uint32_t *pCount)
|
||||
{
|
||||
int32_t msgCount = 0;
|
||||
if (pCount)
|
||||
*pCount = 0;
|
||||
|
||||
nsCOMPtr<nsIInputStream> inputStream;
|
||||
nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), inFile);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIMsgPluggableStore> msgStore;
|
||||
rv = dstFolder->GetMsgStore(getter_AddRefs(msgStore));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t * pIndex;
|
||||
uint32_t indexSize;
|
||||
uint32_t * pFlags;
|
||||
uint64_t * pTime;
|
||||
|
||||
if (!ReadIndex(inputStream, &pIndex, &indexSize)) {
|
||||
IMPORT_LOG1("No messages found in mailbox: %s\n", NS_LossyConvertUTF16toASCII(name.get()));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
pTime = new uint64_t[ indexSize];
|
||||
pFlags = new uint32_t[ indexSize];
|
||||
char * pBuffer = new char[kMailboxBufferSize];
|
||||
if (!(*pAbort))
|
||||
ConvertIndex(inputStream, pBuffer, pIndex, indexSize, pFlags, pTime);
|
||||
|
||||
uint32_t block[4];
|
||||
int32_t sepLen = (int32_t) strlen(m_pFromLineSep);
|
||||
uint32_t written;
|
||||
|
||||
/*
|
||||
Each block is:
|
||||
marker - matches file offset
|
||||
block length
|
||||
text length in block
|
||||
pointer to next block. (0 if end)
|
||||
|
||||
Each message is made up of a linked list of block data.
|
||||
So what we do for each message is:
|
||||
1. Read the first block data.
|
||||
2. Write out the From message separator if the message doesn't already
|
||||
start with one.
|
||||
3. If the block of data doesn't end with CRLF then a line is broken into two blocks,
|
||||
so save the incomplete line for later process when we read the next block. Then
|
||||
write out the block excluding the partial line at the end of the block (if exists).
|
||||
4. If there's next block of data then read next data block. Otherwise we're done.
|
||||
If we found a partial line in step #3 then find the rest of the line from the
|
||||
current block and write out this line separately.
|
||||
5. Reset some of the control variables and repeat step #3.
|
||||
*/
|
||||
|
||||
uint32_t didBytes = 0;
|
||||
uint32_t next, size;
|
||||
char *pStart, *pEnd, *partialLineStart;
|
||||
nsAutoCString partialLine, tempLine;
|
||||
nsCOMPtr<nsIOutputStream> outputStream;
|
||||
rv = NS_OK;
|
||||
|
||||
for (uint32_t i = 0; (i < indexSize) && !(*pAbort); i++)
|
||||
{
|
||||
if (! pIndex[i])
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsIMsgDBHdr> msgHdr;
|
||||
bool reusable;
|
||||
|
||||
rv = msgStore->GetNewMsgOutputStream(dstFolder, getter_AddRefs(msgHdr), &reusable,
|
||||
getter_AddRefs(outputStream));
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
IMPORT_LOG1( "Mbx getting outputstream error: 0x%lx\n", rv);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ReadBytes(inputStream, block, pIndex[i], 16) && (block[0] == pIndex[i]) &&
|
||||
(block[2] < kMailboxBufferSize) && (ReadBytes(inputStream, pBuffer, kDontSeek, block[2])))
|
||||
{
|
||||
// block[2] contains the chars in the buffer (ie, buf content size).
|
||||
// block[3] contains offset to the next block of data (0 means no more data).
|
||||
size = block[2];
|
||||
pStart = pBuffer;
|
||||
pEnd = pStart + size;
|
||||
|
||||
// write out the from separator.
|
||||
rv = NS_ERROR_FAILURE;
|
||||
if (IsFromLine(pBuffer, size))
|
||||
{
|
||||
char *pChar = pStart;
|
||||
while ((pChar < pEnd) && (*pChar != '\r') && (*(pChar+1) != '\n'))
|
||||
pChar++;
|
||||
|
||||
if (pChar < pEnd)
|
||||
{
|
||||
// Get the "From " line so write it out.
|
||||
rv = outputStream->Write(pStart, pChar-pStart+2, &written);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
// Now buffer starts from the 2nd line.
|
||||
pStart = pChar + 2;
|
||||
}
|
||||
}
|
||||
else if (pTime[i])
|
||||
{
|
||||
char result[156] = "";
|
||||
PRExplodedTime xpldTime;
|
||||
char buffer[128] = "";
|
||||
PRTime prt;
|
||||
|
||||
nsOE5File::FileTimeToPRTime((FILETIME *)&pTime[i], &prt);
|
||||
// modeled after nsMsgSend.cpp
|
||||
PR_ExplodeTime(prt, PR_LocalTimeParameters, &xpldTime);
|
||||
PR_FormatTimeUSEnglish(buffer, sizeof(buffer),
|
||||
"%a %b %d %H:%M:%S %Y",
|
||||
&xpldTime);
|
||||
PL_strcpy(result, "From - ");
|
||||
PL_strcpy(result + 7, buffer);
|
||||
PL_strcpy(result + 7 + 24, CRLF);
|
||||
|
||||
rv = outputStream->Write(result, (int32_t) strlen(result), &written);
|
||||
}
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
// Write out the default from line since there is none in the msg.
|
||||
rv = outputStream->Write(m_pFromLineSep, sepLen, &written);
|
||||
// FIXME: Do I need to check the return value of written???
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
}
|
||||
|
||||
char statusLine[50];
|
||||
uint32_t msgFlags = XLATFLAGS(pFlags[i]);
|
||||
PR_snprintf(statusLine, sizeof(statusLine), X_MOZILLA_STATUS_FORMAT MSG_LINEBREAK, msgFlags & 0xFFFF);
|
||||
rv = outputStream->Write(statusLine, strlen(statusLine), &written);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
PR_snprintf(statusLine, sizeof(statusLine), X_MOZILLA_STATUS2_FORMAT MSG_LINEBREAK, msgFlags & 0xFFFF0000);
|
||||
rv = outputStream->Write(statusLine, strlen(statusLine), &written);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
do
|
||||
{
|
||||
partialLine.Truncate();
|
||||
partialLineStart = pEnd;
|
||||
|
||||
// If the buffer doesn't end with CRLF then a line is broken into two blocks,
|
||||
// so save the incomplete line for later process when we read the next block.
|
||||
if ((size > 1) && !(*(pEnd - 2) == '\r' && *(pEnd - 1) == '\n'))
|
||||
{
|
||||
partialLineStart -= 2;
|
||||
while ((partialLineStart >= pStart) && (*partialLineStart != '\r') && (*(partialLineStart+1) != '\n'))
|
||||
partialLineStart--;
|
||||
if (partialLineStart != (pEnd - 2))
|
||||
partialLineStart += 2; // skip over CRLF if we find them.
|
||||
partialLine.Assign(partialLineStart, pEnd - partialLineStart);
|
||||
}
|
||||
|
||||
// Now process the block of data which ends with CRLF.
|
||||
rv = EscapeFromSpaceLine(outputStream, pStart, partialLineStart);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
didBytes += block[2];
|
||||
|
||||
next = block[3];
|
||||
if (! next)
|
||||
{
|
||||
// OK, we're done so flush out the partial line if it's not empty.
|
||||
if (partialLine.Length())
|
||||
rv = EscapeFromSpaceLine(outputStream, (char *)partialLine.get(), (partialLine.get()+partialLine.Length()));
|
||||
}
|
||||
else
|
||||
if (ReadBytes(inputStream, block, next, 16) && (block[0] == next) &&
|
||||
(block[2] < kMailboxBufferSize) && (ReadBytes(inputStream, pBuffer, kDontSeek, block[2])))
|
||||
{
|
||||
// See if we have a partial line from previous block. If so then build a complete
|
||||
// line (ie, take the remaining chars from this block) and process this line. Need
|
||||
// to adjust where data start and size in this case.
|
||||
size = block[2];
|
||||
pStart = pBuffer;
|
||||
pEnd = pStart + size;
|
||||
if (partialLine.Length())
|
||||
{
|
||||
while ((pStart < pEnd) && (*pStart != '\r') && (*(pStart+1) != '\n'))
|
||||
pStart++;
|
||||
if (pStart < pEnd) // if we found a CRLF ..
|
||||
pStart += 2; // .. then copy that too.
|
||||
tempLine.Assign(pBuffer, pStart - pBuffer);
|
||||
partialLine.Append(tempLine);
|
||||
rv = EscapeFromSpaceLine(outputStream, (char *)partialLine.get(), (partialLine.get()+partialLine.Length()));
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
// Adjust where data start and size (since some of the data has been processed).
|
||||
size -= (pStart - pBuffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IMPORT_LOG2("Error reading message from %s at 0x%lx\n", NS_LossyConvertUTF16toASCII(name.get()), pIndex[i]);
|
||||
rv = outputStream->Write("\x0D\x0A", 2, &written);
|
||||
next = 0;
|
||||
}
|
||||
} while (next);
|
||||
|
||||
// Always end a msg with CRLF. This will make sure that OE msgs without body is
|
||||
// correctly recognized as msgs. Otherwise, we'll end up with the following in
|
||||
// the msg folder where the 2nd msg starts right after the headers of the 1st msg:
|
||||
//
|
||||
// From - Jan 1965 00:00:00 <<<--- 1st msg starts here
|
||||
// Subject: Test msg
|
||||
// . . . (more headers)
|
||||
// To: <someone@example.com>
|
||||
// From - Jan 1965 00:00:00 <<<--- 2nd msg starts here
|
||||
// Subject: How are you
|
||||
// . . .(more headers)
|
||||
//
|
||||
// In this case, the 1st msg is not recognized as a msg (it's skipped)
|
||||
// when you open the folder.
|
||||
rv = outputStream->Write("\x0D\x0A", 2, &written);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
IMPORT_LOG0( "Error writing message during OE import\n");
|
||||
msgStore->DiscardNewMessage(outputStream, msgHdr);
|
||||
break;
|
||||
}
|
||||
|
||||
msgStore->FinishNewMessage(outputStream, msgHdr);
|
||||
|
||||
if (!reusable)
|
||||
outputStream->Close();
|
||||
|
||||
msgCount++;
|
||||
if (pCount)
|
||||
*pCount = msgCount;
|
||||
if (pBytesDone)
|
||||
*pBytesDone = didBytes;
|
||||
}
|
||||
else {
|
||||
// Error reading message, should this be logged???
|
||||
IMPORT_LOG2("Error reading message from %s at 0x%lx\n", NS_LossyConvertUTF16toASCII(name.get()), pIndex[i]);
|
||||
*pAbort = true;
|
||||
}
|
||||
}
|
||||
if (outputStream)
|
||||
outputStream->Close();
|
||||
delete [] pBuffer;
|
||||
delete [] pFlags;
|
||||
delete [] pTime;
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
*pAbort = true;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
A message index record consists of:
|
||||
4 byte marker - matches record offset
|
||||
4 bytes size - size of data after this header
|
||||
2 bytes header length - not dependable
|
||||
1 bytes - number of attributes
|
||||
1 byte changes on this object
|
||||
Each attribute is a 4 byte value with the 1st byte being the tag
|
||||
and the remaing 3 bytes being data. The data is either a direct
|
||||
offset of an offset within the message index that points to the
|
||||
data for the tag.
|
||||
attr[0]:
|
||||
-hi bit== 1 means PRUint24 data = attr[1]
|
||||
-hi bit== 0 means (PRUint24) attr[1] = offset into data segment for data
|
||||
-attr[0] & 7f == tag index
|
||||
Header above is 0xC bytes, attr's are number * 4 bytes then follows data segment
|
||||
The data segment length is undefined. The index data is either part of the
|
||||
index structure or the index structure points to address in data that follows
|
||||
index structure table. Use that location to calculate file position of data.
|
||||
MSDN indicates 0x28 attributes possible.
|
||||
|
||||
Current known tags are:
|
||||
0x01 - flags addressed
|
||||
0x81 - flags in attr's next 3 bytes
|
||||
0x02 - a time value - addressed- 8 bytes
|
||||
0x04 - text offset pointer, the data is the offset after the attribute
|
||||
of a 4 byte pointer to the message text <-- addr into data
|
||||
0x05 - offset to truncated subject
|
||||
0x08 - offste to subject
|
||||
0x0D - offset to from
|
||||
0x0E - offset to from addresses
|
||||
0x13 - offset to to name
|
||||
0x45 - offset to to address <----correct --> 0x14
|
||||
0x80 - msgId <-correction-> 0x07 addr to msg id
|
||||
0x84 - direct text offset, direct pointer to message text
|
||||
*/
|
||||
|
||||
void nsOE5File::ConvertIndex(nsIInputStream *pFile, char *pBuffer,
|
||||
uint32_t *pIndex, uint32_t size,
|
||||
uint32_t *pFlags, uint64_t *pTime)
|
||||
{
|
||||
// for each index record, get the actual message offset! If there is a
|
||||
// problem just record the message offset as 0 and the message reading code
|
||||
// can log that error information.
|
||||
// XXXTODO- above error reporting is not done
|
||||
|
||||
uint8_t recordHead[12];
|
||||
uint32_t marker;
|
||||
uint32_t recordSize;
|
||||
uint32_t numAttrs;
|
||||
uint32_t offset;
|
||||
uint32_t attrIndex;
|
||||
uint32_t attrOffset;
|
||||
uint8_t tag;
|
||||
uint32_t tagData;
|
||||
uint32_t flags;
|
||||
uint64_t time;
|
||||
uint32_t dataStart;
|
||||
|
||||
for (uint32_t i = 0; i < size; i++) {
|
||||
offset = 0;
|
||||
flags = 0;
|
||||
time = 0;
|
||||
if (ReadBytes(pFile, recordHead, pIndex[i], 12)) {
|
||||
memcpy(&marker, recordHead, 4);
|
||||
memcpy(&recordSize, recordHead + 4, 4);
|
||||
numAttrs = (uint32_t) recordHead[10];
|
||||
if (marker == pIndex[i] && numAttrs <= kMaxAttrCount) {
|
||||
dataStart = pIndex[i] + 12 + (numAttrs * 4);
|
||||
if (ReadBytes(pFile, pBuffer, kDontSeek, numAttrs * 4)) {
|
||||
attrOffset = 0;
|
||||
for (attrIndex = 0; attrIndex < numAttrs; attrIndex++, attrOffset += 4) {
|
||||
tag = (uint8_t) pBuffer[attrOffset];
|
||||
if (tag == (uint8_t) 0x84) {
|
||||
tagData = 0;
|
||||
memcpy(&tagData, pBuffer + attrOffset + 1, 3);
|
||||
offset = tagData;
|
||||
}
|
||||
else if (tag == (uint8_t) 0x04) {
|
||||
tagData = 0;
|
||||
memcpy(&tagData, pBuffer + attrOffset + 1, 3);
|
||||
ReadBytes(pFile, &offset, dataStart + tagData, 4);
|
||||
}
|
||||
else if (tag == (uint8_t) 0x81) {
|
||||
tagData = 0;
|
||||
memcpy(&tagData, pBuffer + attrOffset +1, 3);
|
||||
flags = tagData;
|
||||
}
|
||||
else if (tag == (uint8_t) 0x01) {
|
||||
tagData = 0;
|
||||
memcpy(&tagData, pBuffer + attrOffset +1, 3);
|
||||
ReadBytes(pFile, &flags, dataStart + tagData, 4);
|
||||
}
|
||||
else if (tag == (uint8_t) 0x02) {
|
||||
tagData = 0;
|
||||
memcpy(&tagData, pBuffer + attrOffset +1, 3);
|
||||
ReadBytes(pFile, &time, dataStart + tagData, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pIndex[i] = offset;
|
||||
pFlags[i] = flags;
|
||||
pTime[i] = time;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool nsOE5File::ReadBytes(nsIInputStream *stream, void *pBuffer, uint32_t offset, uint32_t bytes)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr <nsISeekableStream> seekableStream = do_QueryInterface(stream);
|
||||
if (offset != kDontSeek) {
|
||||
rv = seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, offset);
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!bytes)
|
||||
return true;
|
||||
|
||||
uint32_t cntRead;
|
||||
char * pReadTo = (char *)pBuffer;
|
||||
rv = stream->Read(pReadTo, bytes, &cntRead);
|
||||
return NS_SUCCEEDED(rv) && cntRead == bytes;
|
||||
|
||||
}
|
||||
|
||||
52
mailnews/import/oexpress/nsOE5File.h
Normal file
52
mailnews/import/oexpress/nsOE5File.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#ifndef nsOE5File_h___
|
||||
#define nsOE5File_h___
|
||||
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
#include <windows.h>
|
||||
|
||||
class nsIInputStream;
|
||||
|
||||
class nsOE5File
|
||||
{
|
||||
public:
|
||||
/* pFile must already be open for reading. */
|
||||
static bool VerifyLocalMailFile(nsIFile *pFile);
|
||||
/* pFile must NOT be open for reading */
|
||||
static bool IsLocalMailFile(nsIFile *pFile);
|
||||
|
||||
static bool ReadIndex(nsIInputStream *pFile, uint32_t **ppIndex, uint32_t *pSize);
|
||||
|
||||
static nsresult ImportMailbox(uint32_t *pBytesDone, bool *pAbort,
|
||||
nsString& name, nsIFile *inFile,
|
||||
nsIMsgFolder *pDstFolder, uint32_t *pCount);
|
||||
|
||||
static void FileTimeToPRTime(const FILETIME *filetime, PRTime *prtm);
|
||||
|
||||
private:
|
||||
typedef struct {
|
||||
uint32_t * pIndex;
|
||||
uint32_t count;
|
||||
uint32_t alloc;
|
||||
} PRUint32Array;
|
||||
|
||||
static const char *m_pFromLineSep;
|
||||
|
||||
static bool ReadBytes(nsIInputStream *stream, void *pBuffer, uint32_t offset, uint32_t bytes);
|
||||
static uint32_t ReadMsgIndex(nsIInputStream *file, uint32_t offset, PRUint32Array *pArray);
|
||||
static void ConvertIndex(nsIInputStream *pFile, char *pBuffer, uint32_t *pIndex,
|
||||
uint32_t size, uint32_t *pFlags, uint64_t *pTime);
|
||||
static bool IsFromLine(char *pLine, uint32_t len);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* nsOE5File_h___ */
|
||||
396
mailnews/import/oexpress/nsOEAddressIterator.cpp
Normal file
396
mailnews/import/oexpress/nsOEAddressIterator.cpp
Normal file
|
|
@ -0,0 +1,396 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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/. */
|
||||
|
||||
|
||||
/*
|
||||
|
||||
A sample of XPConnect. This file contains an implementation of
|
||||
nsISample.
|
||||
|
||||
*/
|
||||
#include "nscore.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIImportService.h"
|
||||
#include "nsIImportFieldMap.h"
|
||||
#include "nsABBaseCID.h"
|
||||
#include "nsIAbCard.h"
|
||||
#include "prprf.h"
|
||||
|
||||
#include "nsOEAddressIterator.h"
|
||||
|
||||
#include "OEDebugLog.h"
|
||||
|
||||
typedef struct {
|
||||
int32_t mozField;
|
||||
int32_t multiLine;
|
||||
ULONG mapiTag;
|
||||
} MAPIFields;
|
||||
|
||||
enum {
|
||||
ieidPR_DISPLAY_NAME = 0,
|
||||
ieidPR_ENTRYID,
|
||||
ieidPR_OBJECT_TYPE,
|
||||
ieidMax
|
||||
};
|
||||
|
||||
/*
|
||||
Fields in MAPI, not in Mozilla
|
||||
PR_OFFICE_LOCATION
|
||||
FIX - PR_BIRTHDAY - stored as PT_SYSTIME - FIX to extract for moz address book birthday
|
||||
PR_DISPLAY_NAME_PREFIX - Mr., Mrs. Dr., etc.
|
||||
PR_SPOUSE_NAME
|
||||
PR_GENDER - integer, not text
|
||||
FIX - PR_CONTACT_EMAIL_ADDRESSES - multiuline strings for email addresses, needs
|
||||
parsing to get secondary email address for mozilla
|
||||
*/
|
||||
|
||||
#define kIsMultiLine -2
|
||||
#define kNoMultiLine -1
|
||||
|
||||
static MAPIFields gMapiFields[] = {
|
||||
{ 35, kIsMultiLine, PR_COMMENT},
|
||||
{ 6, kNoMultiLine, PR_BUSINESS_TELEPHONE_NUMBER},
|
||||
{ 7, kNoMultiLine, PR_HOME_TELEPHONE_NUMBER},
|
||||
{ 25, kNoMultiLine, PR_COMPANY_NAME},
|
||||
{ 23, kNoMultiLine, PR_TITLE},
|
||||
{ 10, kNoMultiLine, PR_CELLULAR_TELEPHONE_NUMBER},
|
||||
{ 9, kNoMultiLine, PR_PAGER_TELEPHONE_NUMBER},
|
||||
{ 8, kNoMultiLine, PR_BUSINESS_FAX_NUMBER},
|
||||
{ 8, kNoMultiLine, PR_HOME_FAX_NUMBER},
|
||||
{ 22, kNoMultiLine, PR_COUNTRY},
|
||||
{ 19, kNoMultiLine, PR_LOCALITY},
|
||||
{ 20, kNoMultiLine, PR_STATE_OR_PROVINCE},
|
||||
{ 17, 18, PR_STREET_ADDRESS},
|
||||
{ 21, kNoMultiLine, PR_POSTAL_CODE},
|
||||
{ 27, kNoMultiLine, PR_PERSONAL_HOME_PAGE},
|
||||
{ 26, kNoMultiLine, PR_BUSINESS_HOME_PAGE},
|
||||
{ 13, kNoMultiLine, PR_HOME_ADDRESS_CITY},
|
||||
{ 16, kNoMultiLine, PR_HOME_ADDRESS_COUNTRY},
|
||||
{ 15, kNoMultiLine, PR_HOME_ADDRESS_POSTAL_CODE},
|
||||
{ 14, kNoMultiLine, PR_HOME_ADDRESS_STATE_OR_PROVINCE},
|
||||
{ 11, 12, PR_HOME_ADDRESS_STREET},
|
||||
{ 24, kNoMultiLine, PR_DEPARTMENT_NAME}
|
||||
};
|
||||
|
||||
nsOEAddressIterator::nsOEAddressIterator(CWAB *pWab, nsIAddrDatabase *database)
|
||||
{
|
||||
m_pWab = pWab;
|
||||
m_database = database;
|
||||
}
|
||||
|
||||
nsOEAddressIterator::~nsOEAddressIterator()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult nsOEAddressIterator::EnumUser(const char16_t * pName, LPENTRYID pEid, ULONG cbEid)
|
||||
{
|
||||
IMPORT_LOG1("User: %S\n", pName);
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (m_database) {
|
||||
LPMAILUSER pUser = m_pWab->GetUser(cbEid, pEid);
|
||||
if (pUser) {
|
||||
// Get a new row from the database!
|
||||
nsCOMPtr <nsIMdbRow> newRow;
|
||||
rv = m_database->GetNewRow(getter_AddRefs(newRow));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (newRow && BuildCard(pName, newRow, pUser))
|
||||
{
|
||||
rv = m_database->AddCardRowToDB(newRow);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
IMPORT_LOG0("* Added entry to address book database\n");
|
||||
nsString eMail;
|
||||
|
||||
LPSPropValue pProp = m_pWab->GetUserProperty(pUser, PR_EMAIL_ADDRESS);
|
||||
if (pProp)
|
||||
{
|
||||
m_pWab->GetValueString(pProp, eMail);
|
||||
SanitizeValue(eMail);
|
||||
m_pWab->FreeProperty(pProp);
|
||||
m_listRows.Put(eMail, newRow);
|
||||
}
|
||||
}
|
||||
m_pWab->ReleaseUser(pUser);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void nsOEAddressIterator::FindListRow(nsString &eMail, nsIMdbRow **cardRow)
|
||||
{
|
||||
m_listRows.Get(eMail,cardRow);
|
||||
}
|
||||
|
||||
nsresult nsOEAddressIterator::EnumList(const char16_t * pName, LPENTRYID pEid, ULONG cbEid, LPMAPITABLE lpTable)
|
||||
{
|
||||
// If no name provided then we're done.
|
||||
if (!pName || !(*pName))
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
HRESULT hr = E_FAIL;
|
||||
// Make sure we have db to work with.
|
||||
if (!m_database)
|
||||
return rv;
|
||||
|
||||
nsCOMPtr <nsIMdbRow> listRow;
|
||||
rv = m_database->GetNewListRow(getter_AddRefs(listRow));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = m_database->AddListName(listRow, NS_ConvertUTF16toUTF8(pName).get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = m_database->AddCardRowToDB(listRow);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = m_database->AddListDirNode(listRow);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
LPSRowSet lpRowAB = NULL;
|
||||
ULONG lpcbEID = 0;
|
||||
LPENTRYID lpEID = NULL;
|
||||
ULONG rowCount = 0;
|
||||
int cNumRows = 0;
|
||||
int numListElems = 0;
|
||||
nsAutoString uniStr;
|
||||
|
||||
hr = lpTable->GetRowCount(0, &rowCount);
|
||||
//
|
||||
hr = lpTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL);
|
||||
|
||||
if(HR_FAILED(hr))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Read all the rows of the table one by one
|
||||
do
|
||||
{
|
||||
hr = lpTable->QueryRows(1, 0, &lpRowAB);
|
||||
|
||||
if(HR_FAILED(hr))
|
||||
break;
|
||||
|
||||
if(lpRowAB)
|
||||
{
|
||||
cNumRows = lpRowAB->cRows;
|
||||
if (cNumRows)
|
||||
{
|
||||
LPTSTR lpsz = lpRowAB->aRow[0].lpProps[ieidPR_DISPLAY_NAME].Value.lpszA;
|
||||
LPENTRYID lpEID = (LPENTRYID) lpRowAB->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.lpb;
|
||||
ULONG cbEID = lpRowAB->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.cb;
|
||||
|
||||
// There are 2 kinds of objects - the MAPI_MAILUSER contact object
|
||||
// and the MAPI_DISTLIST contact object
|
||||
// For distribution lists, we will only consider MAILUSER
|
||||
// objects since we can't nest lists yet.
|
||||
if(lpRowAB->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.l == MAPI_MAILUSER)
|
||||
{
|
||||
LPMAILUSER pUser = m_pWab->GetUser(cbEID, lpEID);
|
||||
LPSPropValue pProp = m_pWab->GetUserProperty(pUser, PR_EMAIL_ADDRESS);
|
||||
nsString eMail;
|
||||
|
||||
nsCOMPtr <nsIMdbRow> cardRow;
|
||||
|
||||
m_pWab->GetValueString(pProp, eMail);
|
||||
SanitizeValue(eMail);
|
||||
FindListRow(eMail, getter_AddRefs(cardRow));
|
||||
if (cardRow)
|
||||
{
|
||||
nsCOMPtr <nsIAbCard> userCard;
|
||||
nsCOMPtr <nsIAbCard> newCard;
|
||||
userCard = do_CreateInstance(NS_ABMDBCARD_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
m_database->InitCardFromRow(userCard,cardRow);
|
||||
|
||||
m_database->AddListCardColumnsToRow(userCard, listRow, ++numListElems,
|
||||
getter_AddRefs(newCard),
|
||||
true, nullptr, nullptr);
|
||||
}
|
||||
m_pWab->FreeProperty(pProp);
|
||||
m_pWab->ReleaseUser(pUser);
|
||||
}
|
||||
}
|
||||
m_pWab->FreeProws(lpRowAB);
|
||||
}
|
||||
} while (SUCCEEDED(hr) && cNumRows && lpRowAB);
|
||||
|
||||
m_database->SetListAddressTotal(listRow, numListElems);
|
||||
return rv;
|
||||
}
|
||||
|
||||
void nsOEAddressIterator::SanitizeValue(nsString& val)
|
||||
{
|
||||
MsgReplaceSubstring(val, NS_LITERAL_STRING("\r\n"), NS_LITERAL_STRING(", "));
|
||||
MsgReplaceChar(val, "\r\n", ',');
|
||||
}
|
||||
|
||||
void nsOEAddressIterator::SplitString(nsString& val1, nsString& val2)
|
||||
{
|
||||
// Find the last line if there is more than one!
|
||||
int32_t idx = val1.RFind("\x0D\x0A");
|
||||
int32_t cnt = 2;
|
||||
if (idx == -1) {
|
||||
cnt = 1;
|
||||
idx = val1.RFindChar(13);
|
||||
}
|
||||
if (idx == -1)
|
||||
idx= val1.RFindChar(10);
|
||||
if (idx != -1) {
|
||||
val2 = Substring(val1, idx + cnt);
|
||||
val1.SetLength(idx);
|
||||
SanitizeValue(val1);
|
||||
}
|
||||
}
|
||||
|
||||
void nsOEAddressIterator::SetBirthDay(nsIMdbRow *newRow, PRTime& birthDay)
|
||||
{
|
||||
PRExplodedTime exploded;
|
||||
PR_ExplodeTime(birthDay, PR_LocalTimeParameters, &exploded);
|
||||
|
||||
char stringValue[5];
|
||||
PR_snprintf(stringValue, sizeof(stringValue), "%04d", exploded.tm_year);
|
||||
m_database->AddBirthYear(newRow, stringValue);
|
||||
PR_snprintf(stringValue, sizeof(stringValue), "%02d", exploded.tm_month + 1);
|
||||
m_database->AddBirthMonth(newRow, stringValue);
|
||||
PR_snprintf(stringValue, sizeof(stringValue), "%02d", exploded.tm_mday);
|
||||
m_database->AddBirthDay(newRow, stringValue);
|
||||
}
|
||||
|
||||
bool nsOEAddressIterator::BuildCard(const char16_t * pName, nsIMdbRow *newRow, LPMAILUSER pUser)
|
||||
{
|
||||
|
||||
nsString lastName;
|
||||
nsString firstName;
|
||||
nsString eMail;
|
||||
nsString nickName;
|
||||
nsString middleName;
|
||||
PRTime birthDay = 0;
|
||||
|
||||
LPSPropValue pProp = m_pWab->GetUserProperty(pUser, PR_EMAIL_ADDRESS);
|
||||
if (pProp) {
|
||||
m_pWab->GetValueString(pProp, eMail);
|
||||
SanitizeValue(eMail);
|
||||
m_pWab->FreeProperty(pProp);
|
||||
}
|
||||
pProp = m_pWab->GetUserProperty(pUser, PR_GIVEN_NAME);
|
||||
if (pProp) {
|
||||
m_pWab->GetValueString(pProp, firstName);
|
||||
SanitizeValue(firstName);
|
||||
m_pWab->FreeProperty(pProp);
|
||||
}
|
||||
pProp = m_pWab->GetUserProperty(pUser, PR_SURNAME);
|
||||
if (pProp) {
|
||||
m_pWab->GetValueString(pProp, lastName);
|
||||
SanitizeValue(lastName);
|
||||
m_pWab->FreeProperty(pProp);
|
||||
}
|
||||
pProp = m_pWab->GetUserProperty(pUser, PR_MIDDLE_NAME);
|
||||
if (pProp) {
|
||||
m_pWab->GetValueString(pProp, middleName);
|
||||
SanitizeValue(middleName);
|
||||
m_pWab->FreeProperty(pProp);
|
||||
}
|
||||
pProp = m_pWab->GetUserProperty(pUser, PR_NICKNAME);
|
||||
if (pProp) {
|
||||
m_pWab->GetValueString(pProp, nickName);
|
||||
SanitizeValue(nickName);
|
||||
m_pWab->FreeProperty(pProp);
|
||||
}
|
||||
|
||||
// The idea here is that firstName and lastName cannot both be empty!
|
||||
if (firstName.IsEmpty() && lastName.IsEmpty())
|
||||
firstName = pName;
|
||||
|
||||
nsString displayName;
|
||||
pProp = m_pWab->GetUserProperty(pUser, PR_DISPLAY_NAME);
|
||||
if (pProp) {
|
||||
m_pWab->GetValueString(pProp, displayName);
|
||||
SanitizeValue(displayName);
|
||||
m_pWab->FreeProperty(pProp);
|
||||
}
|
||||
if (displayName.IsEmpty()) {
|
||||
if (firstName.IsEmpty())
|
||||
displayName = pName;
|
||||
else {
|
||||
displayName = firstName;
|
||||
if (!middleName.IsEmpty()) {
|
||||
displayName.Append(char16_t(' '));
|
||||
displayName.Append(middleName);
|
||||
}
|
||||
if (!lastName.IsEmpty()) {
|
||||
displayName.Append(char16_t(' '));
|
||||
displayName.Append(lastName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pProp = m_pWab->GetUserProperty(pUser, PR_BIRTHDAY);
|
||||
if (pProp) {
|
||||
m_pWab->GetValueTime(pProp, birthDay);
|
||||
m_pWab->FreeProperty(pProp);
|
||||
}
|
||||
|
||||
// We now have the required fields
|
||||
// write them out followed by any optional fields!
|
||||
if (!displayName.IsEmpty())
|
||||
m_database->AddDisplayName(newRow, NS_ConvertUTF16toUTF8(displayName).get());
|
||||
if (!firstName.IsEmpty())
|
||||
m_database->AddFirstName(newRow, NS_ConvertUTF16toUTF8(firstName).get());
|
||||
if (!lastName.IsEmpty())
|
||||
m_database->AddLastName(newRow, NS_ConvertUTF16toUTF8(lastName).get());
|
||||
if (!nickName.IsEmpty())
|
||||
m_database->AddNickName(newRow, NS_ConvertUTF16toUTF8(nickName).get());
|
||||
if (!eMail.IsEmpty())
|
||||
m_database->AddPrimaryEmail(newRow, NS_ConvertUTF16toUTF8(eMail).get());
|
||||
|
||||
if (birthDay)
|
||||
SetBirthDay(newRow, birthDay);
|
||||
|
||||
// Do all of the extra fields!
|
||||
|
||||
nsString value;
|
||||
nsString line2;
|
||||
nsresult rv;
|
||||
// Create a field map
|
||||
|
||||
nsCOMPtr<nsIImportService> impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsIImportFieldMap * pFieldMap = nullptr;
|
||||
rv = impSvc->CreateNewFieldMap(&pFieldMap);
|
||||
if (NS_SUCCEEDED(rv) && pFieldMap) {
|
||||
int max = sizeof(gMapiFields) / sizeof(MAPIFields);
|
||||
for (int i = 0; i < max; i++) {
|
||||
pProp = m_pWab->GetUserProperty(pUser, gMapiFields[i].mapiTag);
|
||||
if (pProp) {
|
||||
m_pWab->GetValueString(pProp, value);
|
||||
m_pWab->FreeProperty(pProp);
|
||||
if (!value.IsEmpty()) {
|
||||
if (gMapiFields[i].multiLine == kNoMultiLine) {
|
||||
SanitizeValue(value);
|
||||
pFieldMap->SetFieldValue(m_database, newRow, gMapiFields[i].mozField, value.get());
|
||||
}
|
||||
else if (gMapiFields[i].multiLine == kIsMultiLine) {
|
||||
pFieldMap->SetFieldValue(m_database, newRow, gMapiFields[i].mozField, value.get());
|
||||
}
|
||||
else {
|
||||
line2.Truncate();
|
||||
SplitString(value, line2);
|
||||
if (!value.IsEmpty())
|
||||
pFieldMap->SetFieldValue(m_database, newRow, gMapiFields[i].mozField, value.get());
|
||||
if (!line2.IsEmpty())
|
||||
pFieldMap->SetFieldValue(m_database, newRow, gMapiFields[i].multiLine, line2.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// call fieldMap SetFieldValue based on the table of fields
|
||||
|
||||
NS_RELEASE(pFieldMap);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
36
mailnews/import/oexpress/nsOEAddressIterator.h
Normal file
36
mailnews/import/oexpress/nsOEAddressIterator.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#ifndef nsOEAddressIterator_h___
|
||||
#define nsOEAddressIterator_h___
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "WabObject.h"
|
||||
#include "nsIAddrDatabase.h"
|
||||
#include "mdb.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
|
||||
class nsOEAddressIterator : public CWabIterator {
|
||||
public:
|
||||
nsOEAddressIterator(CWAB *pWab, nsIAddrDatabase *database);
|
||||
~nsOEAddressIterator();
|
||||
|
||||
virtual nsresult EnumUser(const char16_t * pName, LPENTRYID pEid, ULONG cbEid) override;
|
||||
virtual nsresult EnumList(const char16_t * pName, LPENTRYID pEid, ULONG cbEid, LPMAPITABLE table) override;
|
||||
void FindListRow(nsString &eMail, nsIMdbRow **cardRow);
|
||||
|
||||
private:
|
||||
bool BuildCard(const char16_t * pName, nsIMdbRow *card, LPMAILUSER pUser);
|
||||
void SanitizeValue(nsString& val);
|
||||
void SplitString(nsString& val1, nsString& val2);
|
||||
void SetBirthDay(nsIMdbRow *card, PRTime& birthDay);
|
||||
|
||||
CWAB * m_pWab;
|
||||
nsCOMPtr<nsIAddrDatabase> m_database;
|
||||
nsInterfaceHashtable <nsStringHashKey, nsIMdbRow> m_listRows;
|
||||
};
|
||||
|
||||
#endif
|
||||
657
mailnews/import/oexpress/nsOEImport.cpp
Normal file
657
mailnews/import/oexpress/nsOEImport.cpp
Normal file
|
|
@ -0,0 +1,657 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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/. */
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Outlook Express (Win32) import mail and addressbook interfaces
|
||||
|
||||
*/
|
||||
#include "nscore.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIImportService.h"
|
||||
#include "nsOEImport.h"
|
||||
#include "nsIMemory.h"
|
||||
#include "nsOEScanBoxes.h"
|
||||
#include "nsIImportService.h"
|
||||
#include "nsIImportMail.h"
|
||||
#include "nsIImportMailboxDescriptor.h"
|
||||
#include "nsIImportGeneric.h"
|
||||
#include "nsOEMailbox.h"
|
||||
#include "nsIImportAddressBooks.h"
|
||||
#include "nsIImportABDescriptor.h"
|
||||
#include "nsIImportFieldMap.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "WabObject.h"
|
||||
#include "nsOEAddressIterator.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsOE5File.h"
|
||||
#include "nsIAddrDatabase.h"
|
||||
#include "nsOESettings.h"
|
||||
#include "nsTextFormatter.h"
|
||||
#include "nsOEStringBundle.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
|
||||
#include "OEDebugLog.h"
|
||||
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
PRLogModuleInfo *OELOGMODULE = nullptr;
|
||||
|
||||
class ImportOEMailImpl : public nsIImportMail
|
||||
{
|
||||
public:
|
||||
ImportOEMailImpl();
|
||||
|
||||
static nsresult Create(nsIImportMail** aImport);
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
// nsIImportmail interface
|
||||
|
||||
/* void GetDefaultLocation (out nsIFile location, out boolean found, out boolean userVerify); */
|
||||
NS_IMETHOD GetDefaultLocation(nsIFile **location, bool *found, bool *userVerify);
|
||||
|
||||
/* nsIArray FindMailboxes (in nsIFile location); */
|
||||
NS_IMETHOD FindMailboxes(nsIFile *location, nsIArray **_retval);
|
||||
|
||||
NS_IMETHOD ImportMailbox(nsIImportMailboxDescriptor *source,
|
||||
nsIMsgFolder *dstFolder,
|
||||
char16_t **pErrorLog, char16_t **pSuccessLog,
|
||||
bool *fatalError);
|
||||
|
||||
/* unsigned long GetImportProgress (); */
|
||||
NS_IMETHOD GetImportProgress(uint32_t *_retval);
|
||||
|
||||
NS_IMETHOD TranslateFolderName(const nsAString & aFolderName, nsAString & _retval);
|
||||
|
||||
public:
|
||||
static void ReportSuccess(nsString& name, int32_t count, nsString *pStream);
|
||||
static void ReportError(int32_t errorNum, nsString& name, nsString *pStream);
|
||||
static void AddLinebreak(nsString *pStream);
|
||||
static void SetLogs(nsString& success, nsString& error, char16_t **pError, char16_t **pSuccess);
|
||||
|
||||
private:
|
||||
virtual ~ImportOEMailImpl();
|
||||
uint32_t m_bytesDone;
|
||||
};
|
||||
|
||||
|
||||
class ImportOEAddressImpl : public nsIImportAddressBooks
|
||||
{
|
||||
public:
|
||||
ImportOEAddressImpl();
|
||||
|
||||
static nsresult Create(nsIImportAddressBooks** aImport);
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
// nsIImportAddressBooks interface
|
||||
|
||||
NS_IMETHOD GetSupportsMultiple(bool *_retval) { *_retval = false; return NS_OK;}
|
||||
|
||||
NS_IMETHOD GetAutoFind(char16_t **description, bool *_retval);
|
||||
|
||||
NS_IMETHOD GetNeedsFieldMap(nsIFile *pLoc, bool *_retval) { *_retval = false; return NS_OK;}
|
||||
|
||||
NS_IMETHOD GetDefaultLocation(nsIFile **location, bool *found, bool *userVerify);
|
||||
|
||||
NS_IMETHOD FindAddressBooks(nsIFile *location, nsIArray **_retval);
|
||||
|
||||
NS_IMETHOD InitFieldMap(nsIImportFieldMap *fieldMap)
|
||||
{ return NS_ERROR_FAILURE; }
|
||||
|
||||
NS_IMETHOD ImportAddressBook(nsIImportABDescriptor *source,
|
||||
nsIAddrDatabase *destination,
|
||||
nsIImportFieldMap *fieldMap,
|
||||
nsISupports *aSupportService,
|
||||
char16_t **errorLog,
|
||||
char16_t **successLog,
|
||||
bool *fatalError);
|
||||
|
||||
NS_IMETHOD GetImportProgress(uint32_t *_retval);
|
||||
|
||||
NS_IMETHOD GetSampleData(int32_t index, bool *pFound, char16_t **pStr)
|
||||
{ return NS_ERROR_FAILURE;}
|
||||
|
||||
NS_IMETHOD SetSampleLocation(nsIFile *) { return NS_OK; }
|
||||
|
||||
private:
|
||||
virtual ~ImportOEAddressImpl();
|
||||
static void ReportSuccess(nsString& name, nsString *pStream);
|
||||
|
||||
private:
|
||||
CWAB * m_pWab;
|
||||
int m_doneSoFar;
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
nsOEImport::nsOEImport()
|
||||
{
|
||||
// Init logging module.
|
||||
if (!OELOGMODULE)
|
||||
OELOGMODULE = PR_NewLogModule("IMPORT");
|
||||
IMPORT_LOG0("nsOEImport Module Created\n");
|
||||
nsOEStringBundle::GetStringBundle();
|
||||
}
|
||||
|
||||
|
||||
nsOEImport::~nsOEImport()
|
||||
{
|
||||
IMPORT_LOG0("nsOEImport Module Deleted\n");
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsOEImport, nsIImportModule)
|
||||
|
||||
NS_IMETHODIMP nsOEImport::GetName(char16_t **name)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(name);
|
||||
|
||||
*name = nsOEStringBundle::GetStringByID(OEIMPORT_NAME);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsOEImport::GetDescription(char16_t **name)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(name);
|
||||
|
||||
*name = nsOEStringBundle::GetStringByID(OEIMPORT_DESCRIPTION);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsOEImport::GetSupports(char **supports)
|
||||
{
|
||||
NS_PRECONDITION(supports != nullptr, "null ptr");
|
||||
if (! supports)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*supports = strdup(kOESupportsString);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsOEImport::GetSupportsUpgrade(bool *pUpgrade)
|
||||
{
|
||||
NS_PRECONDITION(pUpgrade != nullptr, "null ptr");
|
||||
if (! pUpgrade)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*pUpgrade = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsOEImport::GetImportInterface(const char *pImportType, nsISupports **ppInterface)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(pImportType);
|
||||
NS_ENSURE_ARG_POINTER(ppInterface);
|
||||
|
||||
*ppInterface = nullptr;
|
||||
nsresult rv;
|
||||
if (!strcmp(pImportType, "mail")) {
|
||||
// create the nsIImportMail interface and return it!
|
||||
nsIImportMail * pMail = nullptr;
|
||||
nsIImportGeneric *pGeneric = nullptr;
|
||||
rv = ImportOEMailImpl::Create(&pMail);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIImportService> impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = impSvc->CreateNewGenericMail(&pGeneric);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
pGeneric->SetData("mailInterface", pMail);
|
||||
nsString name;
|
||||
nsOEStringBundle::GetStringByID(OEIMPORT_NAME, name);
|
||||
nsCOMPtr<nsISupportsString> nameString (do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nameString->SetData(name);
|
||||
pGeneric->SetData("name", nameString);
|
||||
rv = pGeneric->QueryInterface(kISupportsIID, (void **)ppInterface);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_IF_RELEASE(pMail);
|
||||
NS_IF_RELEASE(pGeneric);
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!strcmp(pImportType, "addressbook")) {
|
||||
// create the nsIImportMail interface and return it!
|
||||
nsIImportAddressBooks * pAddress = nullptr;
|
||||
nsIImportGeneric * pGeneric = nullptr;
|
||||
rv = ImportOEAddressImpl::Create(&pAddress);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIImportService> impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = impSvc->CreateNewGenericAddressBooks(&pGeneric);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
pGeneric->SetData("addressInterface", pAddress);
|
||||
rv = pGeneric->QueryInterface(kISupportsIID, (void **)ppInterface);
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_IF_RELEASE(pAddress);
|
||||
NS_IF_RELEASE(pGeneric);
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!strcmp(pImportType, "settings")) {
|
||||
nsIImportSettings *pSettings = nullptr;
|
||||
rv = nsOESettings::Create(&pSettings);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
pSettings->QueryInterface(kISupportsIID, (void **)ppInterface);
|
||||
NS_IF_RELEASE(pSettings);
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
nsresult ImportOEMailImpl::Create(nsIImportMail** aImport)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aImport);
|
||||
*aImport = new ImportOEMailImpl();
|
||||
NS_ENSURE_TRUE(*aImport, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ADDREF(*aImport);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ImportOEMailImpl::ImportOEMailImpl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ImportOEMailImpl::~ImportOEMailImpl()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(ImportOEMailImpl, nsIImportMail)
|
||||
|
||||
NS_IMETHODIMP ImportOEMailImpl::TranslateFolderName(const nsAString & aFolderName, nsAString & _retval)
|
||||
{
|
||||
if (aFolderName.LowerCaseEqualsLiteral("deleted items"))
|
||||
_retval = NS_LITERAL_STRING(kDestTrashFolderName);
|
||||
else if (aFolderName.LowerCaseEqualsLiteral("sent items"))
|
||||
_retval = NS_LITERAL_STRING(kDestSentFolderName);
|
||||
else if (aFolderName.LowerCaseEqualsLiteral("outbox"))
|
||||
_retval = NS_LITERAL_STRING(kDestUnsentMessagesFolderName);
|
||||
else
|
||||
_retval = aFolderName;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP ImportOEMailImpl::GetDefaultLocation(nsIFile **ppLoc, bool *found, bool *userVerify)
|
||||
{
|
||||
NS_PRECONDITION(ppLoc != nullptr, "null ptr");
|
||||
NS_PRECONDITION(found != nullptr, "null ptr");
|
||||
NS_PRECONDITION(userVerify != nullptr, "null ptr");
|
||||
if (!ppLoc || !found || !userVerify)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// use scanboxes to find the location.
|
||||
nsresult rv;
|
||||
nsCOMPtr <nsIFile> file = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (nsOEScanBoxes::FindMail(file)) {
|
||||
*found = true;
|
||||
NS_IF_ADDREF(*ppLoc = file);
|
||||
}
|
||||
else {
|
||||
*found = false;
|
||||
*ppLoc = nullptr;
|
||||
}
|
||||
*userVerify = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP ImportOEMailImpl::FindMailboxes(nsIFile *pLoc, nsIArray **ppArray)
|
||||
{
|
||||
NS_PRECONDITION(pLoc != nullptr, "null ptr");
|
||||
NS_PRECONDITION(ppArray != nullptr, "null ptr");
|
||||
if (!pLoc || !ppArray)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
bool exists = false;
|
||||
nsresult rv = pLoc->Exists(&exists);
|
||||
if (NS_FAILED(rv) || !exists)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsOEScanBoxes scan;
|
||||
|
||||
if (!scan.GetMailboxes(pLoc, ppArray))
|
||||
*ppArray = nullptr;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void ImportOEMailImpl::AddLinebreak(nsString *pStream)
|
||||
{
|
||||
if (pStream)
|
||||
pStream->Append(char16_t('\n'));
|
||||
}
|
||||
|
||||
void ImportOEMailImpl::ReportSuccess(nsString& name, int32_t count, nsString *pStream)
|
||||
{
|
||||
if (!pStream)
|
||||
return;
|
||||
// load the success string
|
||||
char16_t *pFmt = nsOEStringBundle::GetStringByID(OEIMPORT_MAILBOX_SUCCESS);
|
||||
char16_t *pText = nsTextFormatter::smprintf(pFmt, name.get(), count);
|
||||
pStream->Append(pText);
|
||||
nsTextFormatter::smprintf_free(pText);
|
||||
nsOEStringBundle::FreeString(pFmt);
|
||||
AddLinebreak(pStream);
|
||||
}
|
||||
|
||||
void ImportOEMailImpl::ReportError(int32_t errorNum, nsString& name, nsString *pStream)
|
||||
{
|
||||
if (!pStream)
|
||||
return;
|
||||
// load the error string
|
||||
char16_t *pFmt = nsOEStringBundle::GetStringByID(errorNum);
|
||||
char16_t *pText = nsTextFormatter::smprintf(pFmt, name.get());
|
||||
pStream->Append(pText);
|
||||
nsTextFormatter::smprintf_free(pText);
|
||||
nsOEStringBundle::FreeString(pFmt);
|
||||
AddLinebreak(pStream);
|
||||
}
|
||||
|
||||
|
||||
void ImportOEMailImpl::SetLogs(nsString& success, nsString& error, char16_t **pError, char16_t **pSuccess)
|
||||
{
|
||||
if (pError)
|
||||
*pError = ToNewUnicode(error);
|
||||
if (pSuccess)
|
||||
*pSuccess = ToNewUnicode(success);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP ImportOEMailImpl::ImportMailbox(nsIImportMailboxDescriptor *pSource,
|
||||
nsIMsgFolder *dstFolder,
|
||||
char16_t **pErrorLog,
|
||||
char16_t **pSuccessLog,
|
||||
bool *fatalError)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(pSource);
|
||||
NS_ENSURE_ARG_POINTER(dstFolder);
|
||||
NS_ENSURE_ARG_POINTER(fatalError);
|
||||
|
||||
nsString success;
|
||||
nsString error;
|
||||
bool abort = false;
|
||||
nsString name;
|
||||
nsString pName;
|
||||
if (NS_SUCCEEDED(pSource->GetDisplayName(getter_Copies(pName))))
|
||||
name = pName;
|
||||
|
||||
uint32_t mailSize = 0;
|
||||
pSource->GetSize(&mailSize);
|
||||
if (mailSize == 0) {
|
||||
ReportSuccess(name, 0, &success);
|
||||
SetLogs(success, error, pErrorLog, pSuccessLog);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr <nsIFile> inFile;
|
||||
if (NS_FAILED(pSource->GetFile(getter_AddRefs(inFile)))) {
|
||||
ReportError(OEIMPORT_MAILBOX_BADSOURCEFILE, name, &error);
|
||||
SetLogs(success, error, pErrorLog, pSuccessLog);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCString pPath;
|
||||
inFile->GetNativePath(pPath);
|
||||
IMPORT_LOG1("Importing Outlook Express mailbox: %s\n", pPath.get());
|
||||
|
||||
m_bytesDone = 0;
|
||||
uint32_t msgCount = 0;
|
||||
nsresult rv;
|
||||
if (nsOE5File::IsLocalMailFile(inFile)) {
|
||||
IMPORT_LOG1("Importing OE5 mailbox: %s!\n", NS_LossyConvertUTF16toASCII(name.get()));
|
||||
rv = nsOE5File::ImportMailbox( &m_bytesDone, &abort, name, inFile, dstFolder, &msgCount);
|
||||
}
|
||||
else {
|
||||
if (CImportMailbox::ImportMailbox( &m_bytesDone, &abort, name, inFile, dstFolder, &msgCount))
|
||||
rv = NS_OK;
|
||||
else
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
ReportSuccess(name, msgCount, &success);
|
||||
else
|
||||
ReportError(OEIMPORT_MAILBOX_CONVERTERROR, name, &error);
|
||||
|
||||
SetLogs(success, error, pErrorLog, pSuccessLog);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP ImportOEMailImpl::GetImportProgress(uint32_t *pDoneSoFar)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(pDoneSoFar);
|
||||
*pDoneSoFar = m_bytesDone;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult ImportOEAddressImpl::Create(nsIImportAddressBooks** aImport)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aImport);
|
||||
|
||||
*aImport = new ImportOEAddressImpl();
|
||||
NS_ENSURE_TRUE(*aImport, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ADDREF(*aImport);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ImportOEAddressImpl::ImportOEAddressImpl()
|
||||
{
|
||||
m_pWab = nullptr;
|
||||
}
|
||||
|
||||
|
||||
ImportOEAddressImpl::~ImportOEAddressImpl()
|
||||
{
|
||||
if (m_pWab)
|
||||
delete m_pWab;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(ImportOEAddressImpl, nsIImportAddressBooks)
|
||||
|
||||
NS_IMETHODIMP ImportOEAddressImpl::GetDefaultLocation(nsIFile **aLocation,
|
||||
bool *aFound,
|
||||
bool *aUserVerify)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLocation);
|
||||
NS_ENSURE_ARG_POINTER(aFound);
|
||||
NS_ENSURE_ARG_POINTER(aUserVerify);
|
||||
|
||||
*aLocation = nullptr;
|
||||
*aUserVerify = true;
|
||||
|
||||
CWAB *wab = new CWAB(nullptr);
|
||||
*aFound = wab->IsAvailable();
|
||||
delete wab;
|
||||
|
||||
if (*aFound) {
|
||||
// Unfortunately WAB interface has no function to obtain address book location.
|
||||
// So we set a fake location here.
|
||||
if (NS_SUCCEEDED(NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR, aLocation)))
|
||||
*aUserVerify = false;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP ImportOEAddressImpl::GetAutoFind(char16_t **description, bool *_retval)
|
||||
{
|
||||
NS_PRECONDITION(description != nullptr, "null ptr");
|
||||
NS_PRECONDITION(_retval != nullptr, "null ptr");
|
||||
if (! description || !_retval)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*_retval = false;
|
||||
nsString str;
|
||||
str.Append(nsOEStringBundle::GetStringByID(OEIMPORT_AUTOFIND));
|
||||
*description = ToNewUnicode(str);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP ImportOEAddressImpl::FindAddressBooks(nsIFile *location, nsIArray **_retval)
|
||||
{
|
||||
NS_PRECONDITION(_retval != nullptr, "null ptr");
|
||||
if (!_retval)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIMutableArray> array(do_CreateInstance(NS_ARRAY_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Make sure we can load up the windows address book...
|
||||
rv = NS_ERROR_FAILURE;
|
||||
|
||||
if (m_pWab)
|
||||
delete m_pWab;
|
||||
|
||||
nsCOMPtr<nsIFile> currentProcessDir;
|
||||
rv = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR,
|
||||
getter_AddRefs(currentProcessDir));
|
||||
bool equals = false;
|
||||
currentProcessDir->Equals(location, &equals);
|
||||
// If the location is not a fake, use it.
|
||||
if (location && !equals) {
|
||||
nsCOMPtr<nsIFile> localFile = do_QueryInterface(location, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
m_pWab = new CWAB(localFile);
|
||||
} else {
|
||||
m_pWab = new CWAB(nullptr);
|
||||
}
|
||||
|
||||
nsIImportABDescriptor * pID;
|
||||
nsISupports * pInterface;
|
||||
nsString str;
|
||||
str.Append(nsOEStringBundle::GetStringByID(OEIMPORT_DEFAULT_NAME));
|
||||
|
||||
if (m_pWab->Loaded()) {
|
||||
// create a new nsIImportABDescriptor and add it to the array
|
||||
nsCOMPtr<nsIImportService> impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = impSvc->CreateNewABDescriptor(&pID);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
pID->SetIdentifier(0x4F453334);
|
||||
pID->SetRef(1);
|
||||
pID->SetSize(100);
|
||||
pID->SetPreferredName(str);
|
||||
rv = pID->QueryInterface(kISupportsIID, (void **) &pInterface);
|
||||
array->AppendElement(pInterface, false);
|
||||
pInterface->Release();
|
||||
pID->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
delete m_pWab;
|
||||
m_pWab = nullptr;
|
||||
}
|
||||
array.forget(_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP ImportOEAddressImpl::ImportAddressBook(nsIImportABDescriptor *source,
|
||||
nsIAddrDatabase *destination,
|
||||
nsIImportFieldMap *fieldMap,
|
||||
nsISupports *aSupportService,
|
||||
char16_t **errorLog,
|
||||
char16_t **successLog,
|
||||
bool *fatalError)
|
||||
{
|
||||
NS_PRECONDITION(source != nullptr, "null ptr");
|
||||
// NS_PRECONDITION(destination != nullptr, "null ptr");
|
||||
// NS_PRECONDITION(fieldMap != nullptr, "null ptr");
|
||||
NS_PRECONDITION(fatalError != nullptr, "null ptr");
|
||||
if (!source || !fatalError)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// we assume it is our one and only address book.
|
||||
if (!m_pWab) {
|
||||
IMPORT_LOG0("Wab not loaded in ImportAddressBook call\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
IMPORT_LOG0("IMPORTING OUTLOOK EXPRESS ADDRESS BOOK\n");
|
||||
|
||||
nsString success;
|
||||
nsString error;
|
||||
if (!source || !destination || !fatalError)
|
||||
{
|
||||
nsOEStringBundle::GetStringByID(OEIMPORT_ADDRESS_BADPARAM, error);
|
||||
if (fatalError)
|
||||
*fatalError = true;
|
||||
ImportOEMailImpl::SetLogs(success, error, errorLog, successLog);
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
m_doneSoFar = 0;
|
||||
nsOEAddressIterator * pIter = new nsOEAddressIterator(m_pWab, destination);
|
||||
HRESULT hr = m_pWab->IterateWABContents(pIter, &m_doneSoFar);
|
||||
delete pIter;
|
||||
|
||||
nsString name;
|
||||
if (SUCCEEDED(hr) && NS_SUCCEEDED(source->GetPreferredName(name)))
|
||||
ReportSuccess(name, &success);
|
||||
else
|
||||
ImportOEMailImpl::ReportError(OEIMPORT_ADDRESS_CONVERTERROR, name, &error);
|
||||
|
||||
ImportOEMailImpl::SetLogs(success, error, errorLog, successLog);
|
||||
|
||||
nsresult rv = destination->Commit(nsAddrDBCommitType::kLargeCommit);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP ImportOEAddressImpl::GetImportProgress(uint32_t *_retval)
|
||||
{
|
||||
NS_PRECONDITION(_retval != nullptr, "null ptr");
|
||||
if (! _retval)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*_retval = (uint32_t) m_doneSoFar;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void ImportOEAddressImpl::ReportSuccess(nsString& name, nsString *pStream)
|
||||
{
|
||||
if (!pStream)
|
||||
return;
|
||||
// load the success string
|
||||
char16_t *pFmt = nsOEStringBundle::GetStringByID(OEIMPORT_ADDRESS_SUCCESS);
|
||||
char16_t *pText = nsTextFormatter::smprintf(pFmt, name.get());
|
||||
pStream->Append(pText);
|
||||
nsTextFormatter::smprintf_free(pText);
|
||||
nsOEStringBundle::FreeString(pFmt);
|
||||
ImportOEMailImpl::AddLinebreak(pStream);
|
||||
}
|
||||
42
mailnews/import/oexpress/nsOEImport.h
Normal file
42
mailnews/import/oexpress/nsOEImport.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#ifndef nsOEImport_h___
|
||||
#define nsOEImport_h___
|
||||
|
||||
#include "nsIImportModule.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#define NS_OEIMPORT_CID \
|
||||
{ /* be0bc880-1742-11d3-a206-00a0cc26da63 */ \
|
||||
0xbe0bc880, 0x1742, 0x11d3, \
|
||||
{0xa2, 0x06, 0x0, 0xa0, 0xcc, 0x26, 0xda, 0x63}}
|
||||
|
||||
|
||||
|
||||
#define kOESupportsString NS_IMPORT_MAIL_STR "," NS_IMPORT_ADDRESS_STR "," NS_IMPORT_SETTINGS_STR
|
||||
|
||||
class nsOEImport : public nsIImportModule
|
||||
{
|
||||
public:
|
||||
|
||||
nsOEImport();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// we suppport the nsIImportModule interface
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
NS_DECL_NSIIMPORTMODULE
|
||||
|
||||
protected:
|
||||
virtual ~nsOEImport();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* nsOEImport_h___ */
|
||||
673
mailnews/import/oexpress/nsOEMailbox.cpp
Normal file
673
mailnews/import/oexpress/nsOEMailbox.cpp
Normal file
|
|
@ -0,0 +1,673 @@
|
|||
/* -*- 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 "nsOEMailbox.h"
|
||||
|
||||
#include "OEDebugLog.h"
|
||||
#include "msgCore.h"
|
||||
#include "prprf.h"
|
||||
#include "nsMsgLocalFolderHdrs.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
#include "nsIMsgHdr.h"
|
||||
#include "nsIMsgPluggableStore.h"
|
||||
#include "nsISeekableStream.h"
|
||||
#include "nsMsgUtils.h"
|
||||
|
||||
class CMbxScanner {
|
||||
public:
|
||||
CMbxScanner(nsString& name, nsIFile * mbxFile, nsIMsgFolder *dstFolder);
|
||||
~CMbxScanner();
|
||||
|
||||
virtual bool Initialize(void);
|
||||
virtual bool DoWork(bool *pAbort, uint32_t *pDone, uint32_t *pCount);
|
||||
|
||||
bool WasErrorFatal(void) { return m_fatalError;}
|
||||
uint32_t BytesProcessed(void) { return m_didBytes;}
|
||||
|
||||
protected:
|
||||
bool WriteMailItem(uint32_t flags, uint32_t offset, uint32_t size, uint32_t *pTotalMsgSize = nullptr);
|
||||
virtual void CleanUp(void);
|
||||
|
||||
private:
|
||||
void ReportWriteError(nsIMsgFolder *folder, bool fatal = true);
|
||||
void ReportReadError(nsIFile * file, bool fatal = true);
|
||||
bool CopyMbxFileBytes(uint32_t flags, uint32_t numBytes);
|
||||
bool IsFromLineKey(uint8_t *pBuf, uint32_t max);
|
||||
|
||||
public:
|
||||
uint32_t m_msgCount;
|
||||
|
||||
protected:
|
||||
uint32_t * m_pDone;
|
||||
nsString m_name;
|
||||
nsCOMPtr<nsIFile> m_mbxFile;
|
||||
nsCOMPtr<nsIMsgFolder> m_dstFolder;
|
||||
nsCOMPtr<nsIInputStream> m_mbxFileInputStream;
|
||||
nsCOMPtr<nsIOutputStream> m_dstOutputStream;
|
||||
nsCOMPtr<nsIMsgPluggableStore> m_msgStore;
|
||||
uint8_t * m_pInBuffer;
|
||||
uint8_t * m_pOutBuffer;
|
||||
uint32_t m_bufSz;
|
||||
uint32_t m_didBytes;
|
||||
bool m_fatalError;
|
||||
int64_t m_mbxFileSize;
|
||||
uint32_t m_mbxOffset;
|
||||
|
||||
static const char * m_pFromLine;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class CIndexScanner : public CMbxScanner {
|
||||
public:
|
||||
CIndexScanner(nsString& name, nsIFile * idxFile, nsIFile * mbxFile, nsIMsgFolder *dstFolder);
|
||||
~CIndexScanner();
|
||||
|
||||
virtual bool Initialize(void);
|
||||
virtual bool DoWork(bool *pAbort, uint32_t *pDone, uint32_t *pCount);
|
||||
|
||||
protected:
|
||||
virtual void CleanUp(void);
|
||||
|
||||
private:
|
||||
bool ValidateIdxFile(void);
|
||||
bool GetMailItem(uint32_t *pFlags, uint32_t *pOffset, uint32_t *pSize);
|
||||
|
||||
|
||||
private:
|
||||
nsCOMPtr <nsIFile> m_idxFile;
|
||||
nsCOMPtr <nsIInputStream> m_idxFileInputStream;
|
||||
uint32_t m_numMessages;
|
||||
uint32_t m_idxOffset;
|
||||
uint32_t m_curItemIndex;
|
||||
};
|
||||
|
||||
|
||||
bool CImportMailbox::ImportMailbox(uint32_t *pDone, bool *pAbort,
|
||||
nsString& name, nsIFile * inFile,
|
||||
nsIMsgFolder *outFolder, uint32_t *pCount)
|
||||
{
|
||||
bool done = false;
|
||||
nsresult rv;
|
||||
nsCOMPtr <nsIFile> idxFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = idxFile->InitWithFile(inFile);
|
||||
if (NS_FAILED(rv)) {
|
||||
IMPORT_LOG0("New file spec failed!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetIndexFile(idxFile)) {
|
||||
|
||||
IMPORT_LOG1("Using index file for: %S\n", name.get());
|
||||
|
||||
CIndexScanner *pIdxScanner = new CIndexScanner(name, idxFile, inFile, outFolder);
|
||||
if (pIdxScanner->Initialize()) {
|
||||
if (pIdxScanner->DoWork(pAbort, pDone, pCount)) {
|
||||
done = true;
|
||||
}
|
||||
else {
|
||||
IMPORT_LOG0("CIndexScanner::DoWork() failed\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
IMPORT_LOG0("CIndexScanner::Initialize() failed\n");
|
||||
}
|
||||
|
||||
delete pIdxScanner;
|
||||
}
|
||||
|
||||
if (done)
|
||||
return done;
|
||||
|
||||
/*
|
||||
something went wrong with the index file, just scan the mailbox
|
||||
file itself.
|
||||
*/
|
||||
CMbxScanner *pMbx = new CMbxScanner(name, inFile, outFolder);
|
||||
if (pMbx->Initialize()) {
|
||||
if (pMbx->DoWork(pAbort, pDone, pCount)) {
|
||||
done = true;
|
||||
}
|
||||
else {
|
||||
IMPORT_LOG0("CMbxScanner::DoWork() failed\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
IMPORT_LOG0("CMbxScanner::Initialize() failed\n");
|
||||
}
|
||||
|
||||
delete pMbx;
|
||||
return done;
|
||||
}
|
||||
|
||||
|
||||
bool CImportMailbox::GetIndexFile(nsIFile* file)
|
||||
{
|
||||
nsCString pLeaf;
|
||||
if (NS_FAILED(file->GetNativeLeafName(pLeaf)))
|
||||
return false;
|
||||
int32_t len = pLeaf.Length();
|
||||
if (len < 5)
|
||||
return false;
|
||||
|
||||
pLeaf.Replace(len - 3, 3, NS_LITERAL_CSTRING("idx"));
|
||||
|
||||
IMPORT_LOG1("Looking for index leaf name: %s\n", pLeaf);
|
||||
|
||||
nsresult rv;
|
||||
rv = file->SetNativeLeafName(pLeaf);
|
||||
|
||||
bool isFile = false;
|
||||
bool exists = false;
|
||||
if (NS_SUCCEEDED(rv)) rv = file->IsFile(&isFile);
|
||||
if (NS_SUCCEEDED(rv)) rv = file->Exists(&exists);
|
||||
|
||||
return (isFile && exists);
|
||||
}
|
||||
|
||||
|
||||
const char *CMbxScanner::m_pFromLine = "From - Mon Jan 1 00:00:00 1965\x0D\x0A";
|
||||
// let's try a 16K buffer and see how well that works?
|
||||
#define kBufferKB 16
|
||||
|
||||
|
||||
CMbxScanner::CMbxScanner(nsString& name, nsIFile* mbxFile,
|
||||
nsIMsgFolder* dstFolder)
|
||||
{
|
||||
m_msgCount = 0;
|
||||
m_name = name;
|
||||
m_mbxFile = mbxFile;
|
||||
m_dstFolder = dstFolder;
|
||||
m_pInBuffer = nullptr;
|
||||
m_pOutBuffer = nullptr;
|
||||
m_bufSz = 0;
|
||||
m_fatalError = false;
|
||||
m_didBytes = 0;
|
||||
m_mbxFileSize = 0;
|
||||
m_mbxOffset = 0;
|
||||
}
|
||||
|
||||
CMbxScanner::~CMbxScanner()
|
||||
{
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
void CMbxScanner::ReportWriteError(nsIMsgFolder * folder, bool fatal)
|
||||
{
|
||||
m_fatalError = fatal;
|
||||
}
|
||||
|
||||
void CMbxScanner::ReportReadError(nsIFile * file, bool fatal)
|
||||
{
|
||||
m_fatalError = fatal;
|
||||
}
|
||||
|
||||
bool CMbxScanner::Initialize(void)
|
||||
{
|
||||
m_bufSz = (kBufferKB * 1024);
|
||||
m_pInBuffer = new uint8_t[m_bufSz];
|
||||
m_pOutBuffer = new uint8_t[m_bufSz];
|
||||
if (!m_pInBuffer || !m_pOutBuffer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_mbxFile->GetFileSize(&m_mbxFileSize);
|
||||
// open the mailbox file...
|
||||
if (NS_FAILED(NS_NewLocalFileInputStream(getter_AddRefs(m_mbxFileInputStream), m_mbxFile))) {
|
||||
CleanUp();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NS_FAILED(m_dstFolder->GetMsgStore(getter_AddRefs(m_msgStore)))) {
|
||||
CleanUp();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#define kMbxHeaderSize 0x0054
|
||||
#define kMbxMessageHeaderSz 16
|
||||
|
||||
bool CMbxScanner::DoWork(bool *pAbort, uint32_t *pDone, uint32_t *pCount)
|
||||
{
|
||||
m_mbxOffset = kMbxHeaderSize;
|
||||
m_didBytes = kMbxHeaderSize;
|
||||
|
||||
while (!(*pAbort) && ((m_mbxOffset + kMbxMessageHeaderSz) < m_mbxFileSize)) {
|
||||
uint32_t msgSz;
|
||||
if (!WriteMailItem(0, m_mbxOffset, 0, &msgSz)) {
|
||||
if (!WasErrorFatal())
|
||||
ReportReadError(m_mbxFile);
|
||||
return false;
|
||||
}
|
||||
m_mbxOffset += msgSz;
|
||||
m_didBytes += msgSz;
|
||||
m_msgCount++;
|
||||
if (pDone)
|
||||
*pDone = m_didBytes;
|
||||
if (pCount)
|
||||
*pCount = m_msgCount;
|
||||
}
|
||||
|
||||
CleanUp();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CMbxScanner::CleanUp(void)
|
||||
{
|
||||
if (m_mbxFileInputStream)
|
||||
m_mbxFileInputStream->Close();
|
||||
if (m_dstOutputStream)
|
||||
m_dstOutputStream->Close();
|
||||
|
||||
delete [] m_pInBuffer;
|
||||
m_pInBuffer = nullptr;
|
||||
|
||||
delete [] m_pOutBuffer;
|
||||
m_pOutBuffer = nullptr;
|
||||
}
|
||||
|
||||
|
||||
#define kNumMbxLongsToRead 4
|
||||
|
||||
bool CMbxScanner::WriteMailItem(uint32_t flags, uint32_t offset, uint32_t size,
|
||||
uint32_t *pTotalMsgSize)
|
||||
{
|
||||
uint32_t values[kNumMbxLongsToRead];
|
||||
int32_t cnt = kNumMbxLongsToRead * sizeof(uint32_t);
|
||||
nsresult rv;
|
||||
uint32_t cntRead;
|
||||
int8_t * pChar = (int8_t *) values;
|
||||
|
||||
nsCOMPtr <nsISeekableStream> seekableStream = do_QueryInterface(m_mbxFileInputStream);
|
||||
rv = seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, offset);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
IMPORT_LOG1("Mbx seek error: 0x%lx\n", offset);
|
||||
return false;
|
||||
}
|
||||
rv = m_mbxFileInputStream->Read((char *) pChar, cnt, &cntRead);
|
||||
if (NS_FAILED(rv) || (cntRead != cnt)) {
|
||||
IMPORT_LOG1("Mbx read error at: 0x%lx\n", offset);
|
||||
return false;
|
||||
}
|
||||
if (values[0] != 0x7F007F00) {
|
||||
IMPORT_LOG2("Mbx tag field doesn't match: 0x%lx, at offset: 0x%lx\n", values[0], offset);
|
||||
return false;
|
||||
}
|
||||
if (size && (values[2] != size)) {
|
||||
IMPORT_LOG3("Mbx size doesn't match idx, mbx: %ld, idx: %ld, at offset: 0x%lx\n", values[2], size, offset);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pTotalMsgSize != nullptr)
|
||||
*pTotalMsgSize = values[2];
|
||||
|
||||
nsCOMPtr<nsIMsgDBHdr> msgHdr;
|
||||
bool reusable;
|
||||
|
||||
rv = m_msgStore->GetNewMsgOutputStream(m_dstFolder, getter_AddRefs(msgHdr), &reusable,
|
||||
getter_AddRefs(m_dstOutputStream));
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
IMPORT_LOG1( "Mbx getting outputstream error: 0x%lx\n", rv);
|
||||
return false;
|
||||
}
|
||||
|
||||
// everything looks kosher...
|
||||
// the actual message text follows and is values[3] bytes long...
|
||||
bool copyOK = CopyMbxFileBytes(flags, values[3]);
|
||||
if (copyOK)
|
||||
m_msgStore->FinishNewMessage(m_dstOutputStream, msgHdr);
|
||||
else {
|
||||
m_msgStore->DiscardNewMessage(m_dstOutputStream, msgHdr);
|
||||
IMPORT_LOG0( "Mbx CopyMbxFileBytes failed\n");
|
||||
}
|
||||
if (!reusable)
|
||||
{
|
||||
m_dstOutputStream->Close();
|
||||
m_dstOutputStream = nullptr;
|
||||
}
|
||||
return copyOK;
|
||||
}
|
||||
|
||||
bool CMbxScanner::IsFromLineKey(uint8_t * pBuf, uint32_t max)
|
||||
{
|
||||
return (max > 5 && (pBuf[0] == 'F') && (pBuf[1] == 'r') && (pBuf[2] == 'o') && (pBuf[3] == 'm') && (pBuf[4] == ' '));
|
||||
}
|
||||
|
||||
|
||||
#define IS_ANY_SPACE(_ch) ((_ch == ' ') || (_ch == '\t') || (_ch == 10) || (_ch == 13))
|
||||
|
||||
|
||||
bool CMbxScanner::CopyMbxFileBytes(uint32_t flags, uint32_t numBytes)
|
||||
{
|
||||
if (!numBytes)
|
||||
return true;
|
||||
|
||||
uint32_t cnt;
|
||||
uint8_t last[2] = {0, 0};
|
||||
uint32_t inIdx = 0;
|
||||
bool first = true;
|
||||
uint8_t * pIn;
|
||||
uint8_t * pStart;
|
||||
int32_t fromLen = strlen(m_pFromLine);
|
||||
nsresult rv;
|
||||
uint32_t cntRead;
|
||||
uint8_t * pChar;
|
||||
|
||||
while (numBytes) {
|
||||
if (numBytes > (m_bufSz - inIdx))
|
||||
cnt = m_bufSz - inIdx;
|
||||
else
|
||||
cnt = numBytes;
|
||||
// Read some of the message from the file...
|
||||
pChar = m_pInBuffer + inIdx;
|
||||
rv = m_mbxFileInputStream->Read((char *) pChar, (int32_t)cnt, &cntRead);
|
||||
if (NS_FAILED(rv) || (cntRead != (int32_t)cnt)) {
|
||||
ReportReadError(m_mbxFile);
|
||||
return false;
|
||||
}
|
||||
// Keep track of the last 2 bytes of the message for terminating EOL logic
|
||||
if (cnt < 2) {
|
||||
last[0] = last[1];
|
||||
last[1] = m_pInBuffer[cnt - 1];
|
||||
}
|
||||
else {
|
||||
last[0] = m_pInBuffer[cnt - 2];
|
||||
last[1] = m_pInBuffer[cnt - 1];
|
||||
}
|
||||
|
||||
inIdx = 0;
|
||||
// Handle the beginning line, don't duplicate an existing From separator
|
||||
if (first) {
|
||||
// check the first buffer to see if it already starts with a From line
|
||||
// If it does, throw it away and use our own
|
||||
if (IsFromLineKey(m_pInBuffer, cnt)) {
|
||||
// skip past the first line
|
||||
while ((inIdx < cnt) && (m_pInBuffer[inIdx] != nsCRT::CR))
|
||||
inIdx++;
|
||||
while ((inIdx < cnt) && (IS_ANY_SPACE(m_pInBuffer[inIdx])))
|
||||
inIdx++;
|
||||
if (inIdx >= cnt) {
|
||||
// This should not occurr - it means the message starts
|
||||
// with a From separator line that is longer than our
|
||||
// file buffer! In this bizarre case, just skip this message
|
||||
// since it is probably bogus anyway.
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
// Begin every message with a From separator
|
||||
rv = m_dstOutputStream->Write(m_pFromLine, fromLen, &cntRead);
|
||||
if (NS_FAILED(rv) || (cntRead != fromLen)) {
|
||||
ReportWriteError(m_dstFolder);
|
||||
return false;
|
||||
}
|
||||
char statusLine[50];
|
||||
uint32_t msgFlags = flags; // need to convert from OE flags to mozilla flags
|
||||
PR_snprintf(statusLine, sizeof(statusLine), X_MOZILLA_STATUS_FORMAT MSG_LINEBREAK, msgFlags & 0xFFFF);
|
||||
rv = m_dstOutputStream->Write(statusLine, strlen(statusLine), &cntRead);
|
||||
if (NS_SUCCEEDED(rv) && cntRead == fromLen)
|
||||
{
|
||||
PR_snprintf(statusLine, sizeof(statusLine), X_MOZILLA_STATUS2_FORMAT MSG_LINEBREAK, msgFlags & 0xFFFF0000);
|
||||
rv = m_dstOutputStream->Write(statusLine, strlen(statusLine), &cntRead);
|
||||
}
|
||||
if (NS_FAILED(rv) || (cntRead != fromLen)) {
|
||||
ReportWriteError(m_dstFolder);
|
||||
return false;
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
|
||||
// Handle generic data, escape any lines that begin with "From "
|
||||
pIn = m_pInBuffer + inIdx;
|
||||
numBytes -= cnt;
|
||||
m_didBytes += cnt;
|
||||
pStart = pIn;
|
||||
cnt -= inIdx;
|
||||
inIdx = 0;
|
||||
while (cnt) {
|
||||
if (*pIn == nsCRT::CR) {
|
||||
// need more in buffer?
|
||||
if ((cnt < 7) && numBytes)
|
||||
break;
|
||||
|
||||
if (cnt > 6) {
|
||||
if ((pIn[1] == nsCRT::LF) && IsFromLineKey(pIn + 2, cnt)) {
|
||||
inIdx += 2;
|
||||
// Match, escape it
|
||||
rv = m_dstOutputStream->Write((const char *)pStart, (int32_t)inIdx, &cntRead);
|
||||
if (NS_SUCCEEDED(rv) && (cntRead == (int32_t)inIdx))
|
||||
rv = m_dstOutputStream->Write(">", 1, &cntRead);
|
||||
if (NS_FAILED(rv) || (cntRead != 1)) {
|
||||
ReportWriteError(m_dstFolder);
|
||||
return false;
|
||||
}
|
||||
|
||||
cnt -= 2;
|
||||
pIn += 2;
|
||||
inIdx = 0;
|
||||
pStart = pIn;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} // == nsCRT::CR
|
||||
|
||||
cnt--;
|
||||
inIdx++;
|
||||
pIn++;
|
||||
}
|
||||
rv = m_dstOutputStream->Write((const char *)pStart, (int32_t)inIdx, &cntRead);
|
||||
if (NS_FAILED(rv) || (cntRead != (int32_t)inIdx)) {
|
||||
ReportWriteError(m_dstFolder);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cnt) {
|
||||
inIdx = cnt;
|
||||
memcpy(m_pInBuffer, pIn, cnt);
|
||||
}
|
||||
else
|
||||
inIdx = 0;
|
||||
}
|
||||
|
||||
// I used to check for an eol before writing one but
|
||||
// it turns out that adding a proper EOL before the next
|
||||
// separator never really hurts so better to be safe
|
||||
// and always do it.
|
||||
// if ((last[0] != nsCRT::CR) || (last[1] != nsCRT::LF)) {
|
||||
rv = m_dstOutputStream->Write("\x0D\x0A", 2, &cntRead);
|
||||
if (NS_FAILED(rv) || (cntRead != 2)) {
|
||||
ReportWriteError(m_dstFolder);
|
||||
return false;
|
||||
}
|
||||
// } // != nsCRT::CR || != nsCRT::LF
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CIndexScanner::CIndexScanner(nsString& name, nsIFile * idxFile,
|
||||
nsIFile * mbxFile, nsIMsgFolder * dstFolder)
|
||||
: CMbxScanner( name, mbxFile, dstFolder)
|
||||
{
|
||||
m_idxFile = idxFile;
|
||||
m_curItemIndex = 0;
|
||||
m_idxOffset = 0;
|
||||
}
|
||||
|
||||
CIndexScanner::~CIndexScanner()
|
||||
{
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
bool CIndexScanner::Initialize(void)
|
||||
{
|
||||
if (!CMbxScanner::Initialize())
|
||||
return false;
|
||||
|
||||
|
||||
nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(m_idxFileInputStream), m_idxFile);
|
||||
if (NS_FAILED(rv)) {
|
||||
CleanUp();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CIndexScanner::ValidateIdxFile(void)
|
||||
{
|
||||
int8_t id[4];
|
||||
int32_t cnt = 4;
|
||||
nsresult rv;
|
||||
uint32_t cntRead;
|
||||
int8_t * pReadTo;
|
||||
|
||||
pReadTo = id;
|
||||
rv = m_idxFileInputStream->Read((char *) pReadTo, cnt, &cntRead);
|
||||
if (NS_FAILED(rv) || (cntRead != cnt))
|
||||
return false;
|
||||
if ((id[0] != 'J') || (id[1] != 'M') || (id[2] != 'F') || (id[3] != '9'))
|
||||
return false;
|
||||
cnt = 4;
|
||||
uint32_t subId;
|
||||
pReadTo = (int8_t *) &subId;
|
||||
rv = m_idxFileInputStream->Read((char *) pReadTo, cnt, &cntRead);
|
||||
if (NS_FAILED(rv) || (cntRead != cnt))
|
||||
return false;
|
||||
if (subId != 0x00010004) {
|
||||
IMPORT_LOG1("Idx file subid doesn't match: 0x%lx\n", subId);
|
||||
return false;
|
||||
}
|
||||
|
||||
pReadTo = (int8_t *) &m_numMessages;
|
||||
rv = m_idxFileInputStream->Read((char *) pReadTo, cnt, &cntRead);
|
||||
if (NS_FAILED(rv) || (cntRead != cnt))
|
||||
return false;
|
||||
|
||||
IMPORT_LOG1("Idx file num messages: %ld\n", m_numMessages);
|
||||
|
||||
m_didBytes += 80;
|
||||
m_idxOffset = 80;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Idx file...
|
||||
Header is 80 bytes, JMF9, subId? 0x00010004, numMessages, fileSize, 1, 0x00010010
|
||||
Entries start at byte 80
|
||||
4 byte numbers
|
||||
Flags? maybe
|
||||
?? who knows
|
||||
index
|
||||
start of this entry in the file
|
||||
length of this record
|
||||
msg offset in mbx
|
||||
msg length in mbx
|
||||
|
||||
*/
|
||||
|
||||
// #define DEBUG_SUBJECT_AND_FLAGS 1
|
||||
#define kNumIdxLongsToRead 7
|
||||
|
||||
bool CIndexScanner::GetMailItem(uint32_t *pFlags, uint32_t *pOffset, uint32_t *pSize)
|
||||
{
|
||||
uint32_t values[kNumIdxLongsToRead];
|
||||
int32_t cnt = kNumIdxLongsToRead * sizeof(uint32_t);
|
||||
int8_t * pReadTo = (int8_t *) values;
|
||||
uint32_t cntRead;
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr <nsISeekableStream> seekableStream = do_QueryInterface(m_idxFileInputStream);
|
||||
rv = seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, m_idxOffset);
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
rv = m_idxFileInputStream->Read((char *) pReadTo, cnt, &cntRead);
|
||||
if (NS_FAILED(rv) || (cntRead != cnt))
|
||||
return false;
|
||||
|
||||
if (values[3] != m_idxOffset) {
|
||||
IMPORT_LOG2("Self pointer invalid: m_idxOffset=0x%lx, self=0x%lx\n", m_idxOffset, values[3]);
|
||||
return false;
|
||||
}
|
||||
|
||||
// So... what do we have here???
|
||||
#ifdef DEBUG_SUBJECT_AND_FLAGS
|
||||
IMPORT_LOG2("Number: %ld, msg offset: 0x%lx, ", values[2], values[5]);
|
||||
IMPORT_LOG2("msg length: %ld, Flags: 0x%lx\n", values[6], values[0]);
|
||||
seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, m_idxOffset + 212);
|
||||
uint32_t subSz = 0;
|
||||
cnt = 4;
|
||||
pReadTo = (int8_t *) &subSz;
|
||||
m_idxFileInputStream->Read((char *) pReadTo, cnt, &cntRead);
|
||||
if ((subSz >= 0) && (subSz < 1024)) {
|
||||
char *pSub = new char[subSz + 1];
|
||||
m_idxFileInputStream->Read(pSub, subSz, &cntRead);
|
||||
pSub[subSz] = 0;
|
||||
IMPORT_LOG1(" Subject: %s\n", pSub);
|
||||
delete [] pSub;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_idxOffset += values[4];
|
||||
m_didBytes += values[4];
|
||||
|
||||
*pFlags = values[0];
|
||||
*pOffset = values[5];
|
||||
*pSize = values[6];
|
||||
return true;
|
||||
}
|
||||
|
||||
#define kOEDeletedFlag 0x0001
|
||||
|
||||
bool CIndexScanner::DoWork(bool *pAbort, uint32_t *pDone, uint32_t *pCount)
|
||||
{
|
||||
m_didBytes = 0;
|
||||
if (!ValidateIdxFile())
|
||||
return false;
|
||||
|
||||
bool failed = false;
|
||||
while ((m_curItemIndex < m_numMessages) && !failed && !(*pAbort)) {
|
||||
uint32_t flags, offset, size;
|
||||
if (!GetMailItem(&flags, &offset, &size)) {
|
||||
CleanUp();
|
||||
return false;
|
||||
}
|
||||
m_curItemIndex++;
|
||||
if (!(flags & kOEDeletedFlag)) {
|
||||
if (!WriteMailItem(flags, offset, size))
|
||||
failed = true;
|
||||
else {
|
||||
m_msgCount++;
|
||||
}
|
||||
}
|
||||
m_didBytes += size;
|
||||
if (pDone)
|
||||
*pDone = m_didBytes;
|
||||
if (pCount)
|
||||
*pCount = m_msgCount;
|
||||
}
|
||||
|
||||
CleanUp();
|
||||
return !failed;
|
||||
}
|
||||
|
||||
|
||||
void CIndexScanner::CleanUp(void)
|
||||
{
|
||||
CMbxScanner::CleanUp();
|
||||
m_idxFileInputStream->Close();
|
||||
}
|
||||
27
mailnews/import/oexpress/nsOEMailbox.h
Normal file
27
mailnews/import/oexpress/nsOEMailbox.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#ifndef nsOEMailbox_h___
|
||||
#define nsOEMailbox_h___
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsIFile.h"
|
||||
|
||||
class nsIMsgFolder;
|
||||
|
||||
class CImportMailbox {
|
||||
public:
|
||||
static bool ImportMailbox(uint32_t *pDone, bool *pAbort, nsString& name,
|
||||
nsIFile * inFile, nsIMsgFolder * outFolder,
|
||||
uint32_t *pCount);
|
||||
|
||||
private:
|
||||
static bool GetIndexFile(nsIFile* mbxFile);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // nsOEMailbox_h__
|
||||
27
mailnews/import/oexpress/nsOERegUtil.cpp
Normal file
27
mailnews/import/oexpress/nsOERegUtil.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/* -*- 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 "nsOERegUtil.h"
|
||||
|
||||
#include "OEDebugLog.h"
|
||||
#include <windows.h>
|
||||
#include "nsIWindowsRegKey.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
|
||||
nsresult nsOERegUtil::GetDefaultUserId(nsAString &aUserId)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIWindowsRegKey> key =
|
||||
do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = key->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
|
||||
NS_LITERAL_STRING("Identities"),
|
||||
nsIWindowsRegKey::ACCESS_QUERY_VALUE);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
return key->ReadStringValue(NS_LITERAL_STRING("Default User ID"), aUserId);
|
||||
}
|
||||
|
||||
20
mailnews/import/oexpress/nsOERegUtil.h
Normal file
20
mailnews/import/oexpress/nsOERegUtil.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#ifndef nsOERegUtil_h___
|
||||
#define nsOERegUtil_h___
|
||||
|
||||
#include <windows.h>
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
class nsOERegUtil
|
||||
{
|
||||
public:
|
||||
static nsresult GetDefaultUserId(nsAString &aUserId);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* nsOERegUtil_h___ */
|
||||
859
mailnews/import/oexpress/nsOEScanBoxes.cpp
Normal file
859
mailnews/import/oexpress/nsOEScanBoxes.cpp
Normal file
|
|
@ -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;
|
||||
}
|
||||
76
mailnews/import/oexpress/nsOEScanBoxes.h
Normal file
76
mailnews/import/oexpress/nsOEScanBoxes.h
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#ifndef nsOEScanBoxes_h___
|
||||
#define nsOEScanBoxes_h___
|
||||
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsIImportModule.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIArray.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIImportService.h"
|
||||
|
||||
class nsIInputStream;
|
||||
|
||||
class nsOEScanBoxes {
|
||||
public:
|
||||
nsOEScanBoxes();
|
||||
~nsOEScanBoxes();
|
||||
|
||||
static bool FindMail(nsIFile *pWhere);
|
||||
|
||||
bool GetMailboxes(nsIFile *pWhere, nsIArray **pArray);
|
||||
|
||||
|
||||
private:
|
||||
typedef struct {
|
||||
uint32_t index;
|
||||
uint32_t parent;
|
||||
int32_t child;
|
||||
int32_t sibling;
|
||||
int32_t type;
|
||||
nsString mailName;
|
||||
nsCString fileName;
|
||||
bool processed; // used by entries on m_pendingChildArray list
|
||||
} MailboxEntry;
|
||||
|
||||
static bool Find50Mail(nsIFile *pWhere);
|
||||
|
||||
void Reset(void);
|
||||
bool FindMailBoxes(nsIFile * descFile);
|
||||
bool Find50MailBoxes(nsIFile * descFile);
|
||||
|
||||
// If find mailboxes fails you can use this routine to get the raw mailbox file names
|
||||
void ScanMailboxDir(nsIFile * srcDir);
|
||||
bool Scan50MailboxDir(nsIFile * srcDir);
|
||||
|
||||
MailboxEntry * GetIndexEntry(uint32_t index);
|
||||
void AddChildEntry(MailboxEntry *pEntry, uint32_t rootIndex);
|
||||
MailboxEntry * NewMailboxEntry(uint32_t id, uint32_t parent, const char *prettyName, char *pFileName);
|
||||
void ProcessPendingChildEntries(uint32_t parent, uint32_t rootIndex, nsTArray<MailboxEntry*> &childArray);
|
||||
void RemoveProcessedChildEntries();
|
||||
|
||||
|
||||
bool ReadLong(nsIInputStream * stream, int32_t& val, uint32_t offset);
|
||||
bool ReadLong(nsIInputStream * stream, uint32_t& val, uint32_t offset);
|
||||
bool ReadString(nsIInputStream * stream, nsString& str, uint32_t offset);
|
||||
bool ReadString(nsIInputStream * stream, nsCString& str, uint32_t offset);
|
||||
uint32_t CountMailboxes(MailboxEntry *pBox);
|
||||
|
||||
void BuildMailboxList(MailboxEntry *pBox, nsIFile * root, int32_t depth, nsIMutableArray *pArray);
|
||||
bool GetMailboxList(nsIFile * root, nsIArray **pArray);
|
||||
|
||||
private:
|
||||
MailboxEntry * m_pFirst;
|
||||
nsTArray<MailboxEntry*> m_entryArray;
|
||||
nsTArray<MailboxEntry*> m_pendingChildArray; // contains child folders whose parent folders have not showed up.
|
||||
|
||||
nsCOMPtr<nsIImportService> mService;
|
||||
};
|
||||
|
||||
#endif // nsOEScanBoxes_h__
|
||||
921
mailnews/import/oexpress/nsOESettings.cpp
Normal file
921
mailnews/import/oexpress/nsOESettings.cpp
Normal file
|
|
@ -0,0 +1,921 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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/. */
|
||||
|
||||
/*
|
||||
|
||||
Outlook Express (Win32) settings
|
||||
|
||||
*/
|
||||
|
||||
#include "nsOESettings.h"
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nscore.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "nsOEImport.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsOERegUtil.h"
|
||||
#include "nsIMsgAccountManager.h"
|
||||
#include "nsIMsgAccount.h"
|
||||
#include "nsIImportSettings.h"
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsMsgCompCID.h"
|
||||
#include "nsMsgI18N.h"
|
||||
#include "nsISmtpService.h"
|
||||
#include "nsISmtpServer.h"
|
||||
#include "nsOEStringBundle.h"
|
||||
#include "OEDebugLog.h"
|
||||
#include "nsIPop3IncomingServer.h"
|
||||
#include "nsIImapIncomingServer.h"
|
||||
#include "nsINntpIncomingServer.h"
|
||||
#include "stdlib.h"
|
||||
#include <windows.h>
|
||||
#include "nsIWindowsRegKey.h"
|
||||
#include "nsComponentManagerUtils.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
|
||||
|
||||
class OESettings {
|
||||
public:
|
||||
static nsresult GetDefaultMailAccount(nsAString &aMailAccount);
|
||||
static nsresult GetCheckMailInterval(uint32_t *aInterval);
|
||||
static nsresult Find50Key(nsIWindowsRegKey **aKey);
|
||||
static nsresult Find40Key(nsIWindowsRegKey **aKey);
|
||||
static nsresult FindAccountsKey(nsIWindowsRegKey **aKey);
|
||||
|
||||
static bool DoImport(nsIMsgAccount **ppAccount);
|
||||
|
||||
static bool DoIMAPServer(nsIMsgAccountManager *aMgr,
|
||||
nsIWindowsRegKey *aKey,
|
||||
const nsString &aServerName,
|
||||
nsIMsgAccount **ppAccount);
|
||||
static bool DoPOP3Server(nsIMsgAccountManager *aMgr,
|
||||
nsIWindowsRegKey *aKey,
|
||||
const nsString &aServerName,
|
||||
nsIMsgAccount **ppAccount);
|
||||
static bool DoNNTPServer(nsIMsgAccountManager *aMgr,
|
||||
nsIWindowsRegKey *aKey,
|
||||
const nsString &aServerName,
|
||||
nsIMsgAccount **ppAccount);
|
||||
|
||||
static void SetIncomingServerProperties(nsIMsgIncomingServer *aServer,
|
||||
nsIWindowsRegKey *aKey,
|
||||
const nsString &aKeyNamePrefix);
|
||||
|
||||
static void SetIdentities(nsIMsgAccountManager *aMgr,
|
||||
nsIMsgAccount *aAccount,
|
||||
nsIWindowsRegKey *aKey,
|
||||
const nsString &aIncomgUserName,
|
||||
int32_t authMethodIncoming, bool isNNTP);
|
||||
static void SetSmtpServer(const nsString &aSmtpServer,
|
||||
nsIWindowsRegKey *aKey,
|
||||
nsIMsgIdentity *aId,
|
||||
const nsString &aIncomgUserName,
|
||||
int32_t authMethodIncoming);
|
||||
static nsresult GetAccountName(nsIWindowsRegKey *aKey,
|
||||
const nsString &aDefaultName,
|
||||
nsAString &aAccountName);
|
||||
static bool IsKB933612Applied();
|
||||
};
|
||||
|
||||
static uint32_t checkNewMailTime;// OE global setting, let's default to 30
|
||||
static bool checkNewMail; // OE global setting, let's default to false
|
||||
// This won't cause unwanted autodownloads-
|
||||
// user can set prefs after import
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
nsresult nsOESettings::Create(nsIImportSettings** aImport)
|
||||
{
|
||||
NS_PRECONDITION(aImport != nullptr, "null ptr");
|
||||
if (! aImport)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aImport = new nsOESettings();
|
||||
if (! *aImport)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*aImport);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsOESettings::nsOESettings()
|
||||
{
|
||||
}
|
||||
|
||||
nsOESettings::~nsOESettings()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsOESettings, nsIImportSettings)
|
||||
|
||||
NS_IMETHODIMP nsOESettings::AutoLocate(char16_t **description, nsIFile **location, bool *_retval)
|
||||
{
|
||||
NS_PRECONDITION(description != nullptr, "null ptr");
|
||||
NS_PRECONDITION(_retval != nullptr, "null ptr");
|
||||
if (!description || !_retval)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*description = nsOEStringBundle::GetStringByID(OEIMPORT_NAME);
|
||||
|
||||
if (location)
|
||||
*location = nullptr;
|
||||
|
||||
*_retval = false;
|
||||
nsCOMPtr<nsIWindowsRegKey> key;
|
||||
if (NS_FAILED(OESettings::Find50Key(getter_AddRefs(key))) &&
|
||||
NS_FAILED(OESettings::Find40Key(getter_AddRefs(key))))
|
||||
return NS_OK;
|
||||
|
||||
if (NS_SUCCEEDED(OESettings::FindAccountsKey(getter_AddRefs(key))))
|
||||
*_retval = true;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsOESettings::SetLocation(nsIFile *location)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsOESettings::Import(nsIMsgAccount **localMailAccount, bool *_retval)
|
||||
{
|
||||
NS_PRECONDITION(_retval != nullptr, "null ptr");
|
||||
|
||||
if (OESettings::DoImport(localMailAccount)) {
|
||||
*_retval = true;
|
||||
IMPORT_LOG0("Settings import appears successful\n");
|
||||
}
|
||||
else {
|
||||
*_retval = false;
|
||||
IMPORT_LOG0("Settings import returned FALSE\n");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult OESettings::GetDefaultMailAccount(nsAString &aMailAccount)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIWindowsRegKey> key =
|
||||
do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString userId;
|
||||
rv = nsOERegUtil::GetDefaultUserId(userId);
|
||||
// OE has default mail account here when it has been
|
||||
// set up by transfer or has multiple identities
|
||||
// look below for orig code that looked in new OE installs
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsAutoString path(NS_LITERAL_STRING("Identities\\"));
|
||||
path.Append(userId);
|
||||
path.AppendLiteral("\\Software\\Microsoft\\Internet Account Manager");
|
||||
rv = key->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
|
||||
path,
|
||||
nsIWindowsRegKey::ACCESS_QUERY_VALUE);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
key->ReadStringValue(NS_LITERAL_STRING("Default Mail Account"), aMailAccount);
|
||||
}
|
||||
|
||||
if (!aMailAccount.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
// else it must be here in original install location from orig code
|
||||
rv = key->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
|
||||
NS_LITERAL_STRING("Software\\Microsoft\\Outlook Express"),
|
||||
nsIWindowsRegKey::ACCESS_QUERY_VALUE);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
return key->ReadStringValue(NS_LITERAL_STRING("Default Mail Account"), aMailAccount);
|
||||
}
|
||||
|
||||
nsresult OESettings::GetCheckMailInterval(uint32_t *aInterval)
|
||||
{
|
||||
nsCOMPtr<nsIWindowsRegKey> key;
|
||||
// 'poll for messages' setting in OE is a global setting
|
||||
// in OE options general tab and in following global OE
|
||||
// registry location.
|
||||
// for all accounts poll interval is a 32 bit value, 0 for
|
||||
// "don't poll", else milliseconds
|
||||
nsresult rv = Find50Key(getter_AddRefs(key));
|
||||
if (NS_FAILED(rv))
|
||||
rv = Find40Key(getter_AddRefs(key));
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIWindowsRegKey> subKey;
|
||||
rv = key->OpenChild(NS_LITERAL_STRING("Mail"),
|
||||
nsIWindowsRegKey::ACCESS_QUERY_VALUE,
|
||||
getter_AddRefs(subKey));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
uint32_t intValue;
|
||||
rv = subKey->ReadIntValue(NS_LITERAL_STRING("Poll For Mail"), &intValue);
|
||||
if (NS_SUCCEEDED(rv) && intValue != PR_UINT32_MAX)
|
||||
*aInterval = intValue / 60000;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult OESettings::FindAccountsKey(nsIWindowsRegKey **aKey)
|
||||
{
|
||||
nsAutoString userId;
|
||||
nsresult rv = nsOERegUtil::GetDefaultUserId(userId);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsAutoString path(NS_LITERAL_STRING("Identities\\"));
|
||||
path.Append(userId);
|
||||
path.AppendLiteral("\\Software\\Microsoft\\Internet Account Manager\\Accounts");
|
||||
|
||||
nsCOMPtr<nsIWindowsRegKey> key =
|
||||
do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = key->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
|
||||
path,
|
||||
nsIWindowsRegKey::ACCESS_QUERY_VALUE |
|
||||
nsIWindowsRegKey::ACCESS_ENUMERATE_SUB_KEYS);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
NS_ADDREF(*aKey = key);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = key->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
|
||||
NS_LITERAL_STRING("Software\\Microsoft\\Internet Account Manager\\Accounts"),
|
||||
nsIWindowsRegKey::ACCESS_QUERY_VALUE |
|
||||
nsIWindowsRegKey::ACCESS_ENUMERATE_SUB_KEYS);
|
||||
NS_IF_ADDREF(*aKey = key);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult OESettings::Find50Key(nsIWindowsRegKey **aKey)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIWindowsRegKey> key =
|
||||
do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString userId;
|
||||
rv = nsOERegUtil::GetDefaultUserId(userId);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsAutoString path(NS_LITERAL_STRING("Identities\\"));
|
||||
path.Append(userId);
|
||||
path.AppendLiteral("\\Software\\Microsoft\\Outlook Express\\5.0");
|
||||
rv = key->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
|
||||
path,
|
||||
nsIWindowsRegKey::ACCESS_QUERY_VALUE);
|
||||
NS_IF_ADDREF(*aKey = key);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult OESettings::Find40Key(nsIWindowsRegKey **aKey)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIWindowsRegKey> key =
|
||||
do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = key->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
|
||||
NS_LITERAL_STRING("Software\\Microsoft\\Outlook Express"),
|
||||
nsIWindowsRegKey::ACCESS_QUERY_VALUE);
|
||||
NS_IF_ADDREF(*aKey = key);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool OESettings::DoImport(nsIMsgAccount **aAccount)
|
||||
{
|
||||
nsCOMPtr<nsIWindowsRegKey> key;
|
||||
nsresult rv = FindAccountsKey(getter_AddRefs(key));
|
||||
if (NS_FAILED(rv)) {
|
||||
IMPORT_LOG0( "*** Error finding Outlook Express registry account keys\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIMsgAccountManager> accMgr =
|
||||
do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
IMPORT_LOG0("*** Failed to create a account manager!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoString defMailName;
|
||||
rv = GetDefaultMailAccount(defMailName);
|
||||
|
||||
checkNewMail = false;
|
||||
checkNewMailTime = 30;
|
||||
rv = GetCheckMailInterval(&checkNewMailTime);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
checkNewMail = true;
|
||||
|
||||
// Iterate the accounts looking for POP3 & IMAP accounts...
|
||||
// Ignore LDAP for now!
|
||||
uint32_t accounts = 0;
|
||||
nsAutoString keyComp;
|
||||
uint32_t childCount = 0;
|
||||
key->GetChildCount(&childCount);
|
||||
for (uint32_t i = 0; i < childCount; i++) {
|
||||
nsAutoString keyName;
|
||||
key->GetChildName(i, keyName);
|
||||
|
||||
nsCOMPtr<nsIWindowsRegKey> subKey;
|
||||
rv = key->OpenChild(keyName,
|
||||
nsIWindowsRegKey::ACCESS_QUERY_VALUE,
|
||||
getter_AddRefs(subKey));
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
nsAutoCString nativeKeyName;
|
||||
NS_CopyUnicodeToNative(keyName, nativeKeyName);
|
||||
IMPORT_LOG1("Opened Outlook Express account: %s\n",
|
||||
nativeKeyName.get());
|
||||
|
||||
nsIMsgAccount *anAccount = nullptr;
|
||||
nsAutoString value;
|
||||
rv = subKey->ReadStringValue(NS_LITERAL_STRING("IMAP Server"), value);
|
||||
if (NS_SUCCEEDED(rv) && DoIMAPServer(accMgr, subKey, value, &anAccount))
|
||||
accounts++;
|
||||
|
||||
rv = subKey->ReadStringValue(NS_LITERAL_STRING("NNTP Server"), value);
|
||||
if (NS_SUCCEEDED(rv) && DoNNTPServer(accMgr, subKey, value, &anAccount))
|
||||
accounts++;
|
||||
|
||||
rv = subKey->ReadStringValue(NS_LITERAL_STRING("POP3 Server"), value);
|
||||
if (NS_SUCCEEDED(rv) && DoPOP3Server(accMgr, subKey, value, &anAccount))
|
||||
accounts++;
|
||||
|
||||
if (anAccount) {
|
||||
// Is this the default account?
|
||||
keyComp = keyName;
|
||||
if (keyComp.Equals(defMailName))
|
||||
accMgr->SetDefaultAccount(anAccount);
|
||||
NS_RELEASE(anAccount);
|
||||
}
|
||||
}
|
||||
|
||||
// Now save the new acct info to pref file.
|
||||
rv = accMgr->SaveAccountInfo();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Can't save account info to pref file");
|
||||
|
||||
return accounts != 0;
|
||||
}
|
||||
|
||||
nsresult OESettings::GetAccountName(nsIWindowsRegKey *aKey,
|
||||
const nsString &aDefaultName,
|
||||
nsAString &aAccountName)
|
||||
{
|
||||
nsresult rv;
|
||||
rv = aKey->ReadStringValue(NS_LITERAL_STRING("Account Name"), aAccountName);
|
||||
if (NS_FAILED(rv))
|
||||
aAccountName.Assign(aDefaultName);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool OESettings::DoIMAPServer(nsIMsgAccountManager *aMgr,
|
||||
nsIWindowsRegKey *aKey,
|
||||
const nsString &aServerName,
|
||||
nsIMsgAccount **ppAccount)
|
||||
{
|
||||
if (ppAccount)
|
||||
*ppAccount = nullptr;
|
||||
|
||||
nsAutoString userName;
|
||||
nsresult rv;
|
||||
rv = aKey->ReadStringValue(NS_LITERAL_STRING("IMAP User Name"), userName);
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
nsAutoCString nativeUserName;
|
||||
NS_CopyUnicodeToNative(userName, nativeUserName);
|
||||
nsAutoCString nativeServerName;
|
||||
NS_CopyUnicodeToNative(aServerName, nativeServerName);
|
||||
// I now have a user name/server name pair, find out if it already exists?
|
||||
nsCOMPtr<nsIMsgIncomingServer> in;
|
||||
rv = aMgr->FindServer(nativeUserName,
|
||||
nativeServerName,
|
||||
NS_LITERAL_CSTRING("imap"),
|
||||
getter_AddRefs(in));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// for an existing server we create another identity,
|
||||
// TB lists under 'manage identities'
|
||||
nsCOMPtr<nsIMsgAccount> account;
|
||||
rv = aMgr->FindAccountForServer(in, getter_AddRefs(account));
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
IMPORT_LOG0("Created an identity and added to existing IMAP incoming server\n");
|
||||
// Fiddle with the identities
|
||||
int32_t authMethod;
|
||||
in->GetAuthMethod(&authMethod);
|
||||
SetIdentities(aMgr, account, aKey, userName, authMethod, false);
|
||||
if (ppAccount)
|
||||
account->QueryInterface(NS_GET_IID(nsIMsgAccount),
|
||||
(void **)ppAccount);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create the incoming server and an account for it?
|
||||
rv = aMgr->CreateIncomingServer(nativeUserName,
|
||||
nativeServerName,
|
||||
NS_LITERAL_CSTRING("imap"),
|
||||
getter_AddRefs(in));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
nsAutoString rootFolder;
|
||||
rv = aKey->ReadStringValue(NS_LITERAL_STRING("IMAP Root Folder"), rootFolder);
|
||||
if (NS_SUCCEEDED(rv) && !rootFolder.IsEmpty()) {
|
||||
nsCOMPtr<nsIImapIncomingServer> imapServer = do_QueryInterface(in);
|
||||
nsAutoCString nativeRootFolder;
|
||||
NS_CopyUnicodeToNative(rootFolder, nativeRootFolder);
|
||||
imapServer->SetServerDirectory(nativeRootFolder);
|
||||
}
|
||||
|
||||
SetIncomingServerProperties(in, aKey, NS_LITERAL_STRING("IMAP "));
|
||||
|
||||
IMPORT_LOG2("Created IMAP server named: %s, userName: %s\n",
|
||||
nativeServerName.get(), nativeUserName.get());
|
||||
|
||||
nsAutoString prettyName;
|
||||
if (NS_SUCCEEDED(GetAccountName(aKey, aServerName, prettyName)))
|
||||
rv = in->SetPrettyName(prettyName);
|
||||
|
||||
// We have a server, create an account.
|
||||
nsCOMPtr<nsIMsgAccount> account;
|
||||
rv = aMgr->CreateAccount(getter_AddRefs(account));
|
||||
if (NS_SUCCEEDED(rv) && account) {
|
||||
rv = account->SetIncomingServer(in);
|
||||
|
||||
IMPORT_LOG0("Created an account and set the IMAP server as the incoming server\n");
|
||||
|
||||
// Fiddle with the identities
|
||||
int32_t authMethod;
|
||||
in->GetAuthMethod(&authMethod);
|
||||
SetIdentities(aMgr, account, aKey, userName, authMethod, false);
|
||||
if (ppAccount)
|
||||
account->QueryInterface(NS_GET_IID(nsIMsgAccount), (void **)ppAccount);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OESettings::DoPOP3Server(nsIMsgAccountManager *aMgr,
|
||||
nsIWindowsRegKey *aKey,
|
||||
const nsString &aServerName,
|
||||
nsIMsgAccount **ppAccount)
|
||||
{
|
||||
if (ppAccount)
|
||||
*ppAccount = nullptr;
|
||||
|
||||
nsAutoString userName;
|
||||
nsresult rv;
|
||||
rv = aKey->ReadStringValue(NS_LITERAL_STRING("POP3 User Name"), userName);
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
nsAutoCString nativeUserName;
|
||||
NS_CopyUnicodeToNative(userName, nativeUserName);
|
||||
nsAutoCString nativeServerName;
|
||||
NS_CopyUnicodeToNative(aServerName, nativeServerName);
|
||||
|
||||
// I now have a user name/server name pair, find out if it already exists?
|
||||
nsCOMPtr<nsIMsgIncomingServer> in;
|
||||
rv = aMgr->FindServer(nativeUserName,
|
||||
nativeServerName,
|
||||
NS_LITERAL_CSTRING("pop3"),
|
||||
getter_AddRefs(in));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
IMPORT_LOG2("Existing POP3 server named: %s, userName: %s\n",
|
||||
nativeUserName.get(), nativeServerName.get());
|
||||
// for an existing server we create another identity,
|
||||
// TB listed under 'manage identities'
|
||||
nsCOMPtr<nsIMsgAccount> account;
|
||||
rv = aMgr->FindAccountForServer(in, getter_AddRefs(account));
|
||||
if (NS_SUCCEEDED(rv) && account) {
|
||||
IMPORT_LOG0("Created identity and added to existing POP3 incoming server.\n");
|
||||
// Fiddle with the identities
|
||||
int32_t authMethod;
|
||||
in->GetAuthMethod(&authMethod);
|
||||
SetIdentities(aMgr, account, aKey, userName, authMethod, false);
|
||||
if (ppAccount)
|
||||
account->QueryInterface(NS_GET_IID(nsIMsgAccount), (void **)ppAccount);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the incoming server and an account for it?
|
||||
rv = aMgr->CreateIncomingServer(nativeUserName,
|
||||
nativeServerName,
|
||||
NS_LITERAL_CSTRING("pop3"),
|
||||
getter_AddRefs( in));
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
SetIncomingServerProperties(in, aKey, NS_LITERAL_STRING("POP3 "));
|
||||
|
||||
nsCOMPtr<nsIPop3IncomingServer> pop3Server = do_QueryInterface(in);
|
||||
if (pop3Server) {
|
||||
// set local folders as the Inbox to use for this POP3 server
|
||||
nsCOMPtr<nsIMsgIncomingServer> localFoldersServer;
|
||||
aMgr->GetLocalFoldersServer(getter_AddRefs(localFoldersServer));
|
||||
|
||||
if (!localFoldersServer)
|
||||
{
|
||||
// If Local Folders does not exist already, create it
|
||||
|
||||
if (NS_FAILED(aMgr->CreateLocalMailAccount())) {
|
||||
IMPORT_LOG0("*** Failed to create Local Folders!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
aMgr->GetLocalFoldersServer(getter_AddRefs(localFoldersServer));
|
||||
}
|
||||
|
||||
// now get the account for this server
|
||||
nsCOMPtr<nsIMsgAccount> localFoldersAccount;
|
||||
aMgr->FindAccountForServer(localFoldersServer, getter_AddRefs(localFoldersAccount));
|
||||
if (localFoldersAccount)
|
||||
{
|
||||
nsCString localFoldersAcctKey;
|
||||
localFoldersAccount->GetKey(localFoldersAcctKey);
|
||||
pop3Server->SetDeferredToAccount(localFoldersAcctKey);
|
||||
}
|
||||
|
||||
uint32_t intValue;
|
||||
rv = aKey->ReadIntValue(NS_LITERAL_STRING("POP3 Skip Account"), &intValue);
|
||||
// OE:0=='Include this account when receiving mail or synchronizing'==
|
||||
// TB:1==AM:Server:advanced:Include this server when getting new mail
|
||||
pop3Server->SetDeferGetNewMail(NS_SUCCEEDED(rv) && intValue == 0);
|
||||
|
||||
rv = aKey->ReadIntValue(NS_LITERAL_STRING("Leave Mail On Server"),
|
||||
&intValue);
|
||||
pop3Server->SetLeaveMessagesOnServer(NS_SUCCEEDED(rv) && intValue == 1);
|
||||
|
||||
rv = aKey->ReadIntValue(NS_LITERAL_STRING("Remove When Deleted"),
|
||||
&intValue);
|
||||
pop3Server->SetDeleteMailLeftOnServer(NS_SUCCEEDED(rv) && intValue == 1);
|
||||
|
||||
rv = aKey->ReadIntValue(NS_LITERAL_STRING("Remove When Expired"),
|
||||
&intValue);
|
||||
pop3Server->SetDeleteByAgeFromServer(NS_SUCCEEDED(rv) && intValue == 1);
|
||||
|
||||
rv = aKey->ReadIntValue(NS_LITERAL_STRING("Expire Days"),
|
||||
&intValue);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
pop3Server->SetNumDaysToLeaveOnServer(static_cast<int32_t>(intValue));
|
||||
}
|
||||
IMPORT_LOG2("Created POP3 server named: %s, userName: %s\n",
|
||||
nativeServerName.get(), nativeUserName.get());
|
||||
nsString prettyName;
|
||||
if (NS_SUCCEEDED(GetAccountName(aKey, aServerName, prettyName)))
|
||||
rv = in->SetPrettyName(prettyName);
|
||||
|
||||
// We have a server, create an account.
|
||||
nsCOMPtr<nsIMsgAccount> account;
|
||||
rv = aMgr->CreateAccount(getter_AddRefs( account));
|
||||
if (NS_SUCCEEDED( rv) && account) {
|
||||
rv = account->SetIncomingServer(in);
|
||||
IMPORT_LOG0("Created a new account and set the incoming server to the POP3 server.\n");
|
||||
|
||||
int32_t authMethod;
|
||||
in->GetAuthMethod(&authMethod);
|
||||
// Fiddle with the identities
|
||||
SetIdentities(aMgr, account, aKey, userName, authMethod, false);
|
||||
if (ppAccount)
|
||||
account->QueryInterface(NS_GET_IID(nsIMsgAccount),
|
||||
(void **)ppAccount);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OESettings::DoNNTPServer(nsIMsgAccountManager *aMgr,
|
||||
nsIWindowsRegKey *aKey,
|
||||
const nsString &aServerName,
|
||||
nsIMsgAccount **ppAccount)
|
||||
{
|
||||
if (ppAccount)
|
||||
*ppAccount = nullptr;
|
||||
|
||||
nsAutoString userName;
|
||||
nsresult rv;
|
||||
// this only exists if NNTP server requires it or not anon login
|
||||
rv = aKey->ReadStringValue(NS_LITERAL_STRING("NNTP User Name"), userName);
|
||||
|
||||
bool result = false;
|
||||
|
||||
nsAutoCString nativeServerName;
|
||||
NS_CopyUnicodeToNative(aServerName, nativeServerName);
|
||||
// I now have a user name/server name pair, find out if it already exists?
|
||||
// NNTP can have empty user name. This is wild card in findserver
|
||||
nsCOMPtr<nsIMsgIncomingServer> in;
|
||||
rv = aMgr->FindServer(EmptyCString(),
|
||||
nativeServerName,
|
||||
NS_LITERAL_CSTRING("nntp"),
|
||||
getter_AddRefs(in));
|
||||
if (NS_FAILED(rv) || (in == nullptr)) {
|
||||
// Create the incoming server and an account for it?
|
||||
rv = aMgr->CreateIncomingServer(EmptyCString(),
|
||||
nativeServerName,
|
||||
NS_LITERAL_CSTRING("nntp"),
|
||||
getter_AddRefs(in));
|
||||
if (NS_SUCCEEDED(rv) && in) {
|
||||
uint32_t port = 0;
|
||||
rv = aKey->ReadIntValue(NS_LITERAL_STRING("NNTP Port"),
|
||||
&port);
|
||||
if (NS_SUCCEEDED(rv) && port && port != 119)
|
||||
in->SetPort(static_cast<int32_t>(port));
|
||||
|
||||
nsAutoCString nativeUserName;
|
||||
NS_CopyUnicodeToNative(userName, nativeUserName);
|
||||
// do nntpincomingserver stuff
|
||||
nsCOMPtr<nsINntpIncomingServer> nntpServer = do_QueryInterface(in);
|
||||
if (nntpServer && !userName.IsEmpty()) {
|
||||
nntpServer->SetPushAuth(true);
|
||||
in->SetUsername(nativeUserName);
|
||||
}
|
||||
|
||||
IMPORT_LOG2("Created NNTP server named: %s, userName: %s\n",
|
||||
nativeServerName.get(), nativeUserName.get());
|
||||
|
||||
nsString prettyName;
|
||||
if (NS_SUCCEEDED(GetAccountName(aKey, aServerName, prettyName)))
|
||||
rv = in->SetPrettyName(prettyName);
|
||||
|
||||
// We have a server, create an account.
|
||||
nsCOMPtr<nsIMsgAccount> account;
|
||||
rv = aMgr->CreateAccount(getter_AddRefs(account));
|
||||
if (NS_SUCCEEDED(rv) && account) {
|
||||
rv = account->SetIncomingServer(in);
|
||||
|
||||
IMPORT_LOG0("Created an account and set the NNTP server as the incoming server\n");
|
||||
|
||||
// Fiddle with the identities
|
||||
SetIdentities(aMgr, account, aKey, userName, 0, true);
|
||||
result = true;
|
||||
if (ppAccount)
|
||||
account->QueryInterface(NS_GET_IID(nsIMsgAccount), (void **)ppAccount);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (NS_SUCCEEDED(rv) && in) {
|
||||
// for the existing server...
|
||||
nsCOMPtr<nsIMsgAccount> account;
|
||||
rv = aMgr->FindAccountForServer(in, getter_AddRefs(account));
|
||||
if (NS_SUCCEEDED(rv) && account) {
|
||||
IMPORT_LOG0("Using existing account and set the NNTP server as the incoming server\n");
|
||||
// Fiddle with the identities
|
||||
SetIdentities(aMgr, account, aKey, userName, 0, true);
|
||||
if (ppAccount)
|
||||
account->QueryInterface(NS_GET_IID(nsIMsgAccount),
|
||||
(void **)ppAccount);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
result = true;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void OESettings::SetIncomingServerProperties(nsIMsgIncomingServer *aServer,
|
||||
nsIWindowsRegKey *aKey,
|
||||
const nsString &aKeyNamePrefix)
|
||||
{
|
||||
nsresult rv;
|
||||
uint32_t secureConnection = 0;
|
||||
nsString keyName(aKeyNamePrefix);
|
||||
keyName.AppendLiteral("Secure Connection");
|
||||
rv = aKey->ReadIntValue(keyName, &secureConnection);
|
||||
if (NS_SUCCEEDED(rv) && secureConnection == 1)
|
||||
aServer->SetSocketType(nsMsgSocketType::SSL);
|
||||
|
||||
uint32_t port = 0;
|
||||
keyName.SetLength(aKeyNamePrefix.Length());
|
||||
keyName.AppendLiteral("Port");
|
||||
rv = aKey->ReadIntValue(keyName, &port);
|
||||
if (NS_SUCCEEDED(rv) && port)
|
||||
aServer->SetPort(static_cast<int32_t>(port));
|
||||
|
||||
int32_t authMethod;
|
||||
uint32_t useSicily = 0;
|
||||
keyName.SetLength(aKeyNamePrefix.Length());
|
||||
keyName.AppendLiteral("Use Sicily");
|
||||
rv = aKey->ReadIntValue(keyName, &useSicily);
|
||||
if (NS_SUCCEEDED(rv) && useSicily)
|
||||
authMethod = nsMsgAuthMethod::secure;
|
||||
else
|
||||
authMethod = nsMsgAuthMethod::passwordCleartext;
|
||||
aServer->SetAuthMethod(authMethod);
|
||||
|
||||
aServer->SetDoBiff(checkNewMail);
|
||||
aServer->SetBiffMinutes(checkNewMailTime);
|
||||
}
|
||||
|
||||
void OESettings::SetIdentities(nsIMsgAccountManager *aMgr,
|
||||
nsIMsgAccount *pAcc,
|
||||
nsIWindowsRegKey *aKey,
|
||||
const nsString &aIncomgUserName,
|
||||
int32_t authMethodIncoming,
|
||||
bool isNNTP)
|
||||
{
|
||||
// Get the relevant information for an identity
|
||||
nsresult rv;
|
||||
nsAutoString name;
|
||||
rv = aKey->ReadStringValue(isNNTP ?
|
||||
NS_LITERAL_STRING("NNTP Display Name") :
|
||||
NS_LITERAL_STRING("SMTP Display Name"),
|
||||
name);
|
||||
nsAutoString email;
|
||||
rv = aKey->ReadStringValue(isNNTP ?
|
||||
NS_LITERAL_STRING("NNTP Email Address") :
|
||||
NS_LITERAL_STRING("SMTP Email Address"),
|
||||
email);
|
||||
nsAutoString reply;
|
||||
rv = aKey->ReadStringValue(isNNTP ?
|
||||
NS_LITERAL_STRING("NNTP Reply To Email Address") :
|
||||
NS_LITERAL_STRING("SMTP Reply To Email Address"),
|
||||
reply);
|
||||
nsAutoString orgName;
|
||||
rv = aKey->ReadStringValue(isNNTP ?
|
||||
NS_LITERAL_STRING("NNTP Organization Name") :
|
||||
NS_LITERAL_STRING("SMTP Organization Name"),
|
||||
orgName);
|
||||
|
||||
nsCOMPtr<nsIMsgIdentity> id;
|
||||
rv = aMgr->CreateIdentity(getter_AddRefs(id));
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
id->SetFullName(name);
|
||||
id->SetOrganization(orgName);
|
||||
|
||||
nsAutoCString nativeEmail;
|
||||
NS_CopyUnicodeToNative(email, nativeEmail);
|
||||
id->SetEmail(nativeEmail);
|
||||
if (!reply.IsEmpty()) {
|
||||
nsAutoCString nativeReply;
|
||||
NS_CopyUnicodeToNative(reply, nativeReply);
|
||||
id->SetReplyTo(nativeReply);
|
||||
}
|
||||
|
||||
// Outlook Express users are used to top style quoting.
|
||||
id->SetReplyOnTop(isNNTP ? 0 : 1);
|
||||
pAcc->AddIdentity(id);
|
||||
|
||||
nsAutoCString nativeName;
|
||||
NS_CopyUnicodeToNative(name, nativeName);
|
||||
IMPORT_LOG0("Created identity and added to the account\n");
|
||||
IMPORT_LOG1("\tname: %s\n", nativeName.get());
|
||||
IMPORT_LOG1("\temail: %s\n", nativeEmail.get());
|
||||
|
||||
if (isNNTP) // NNTP does not use SMTP in OE or TB
|
||||
return;
|
||||
nsAutoString smtpServer;
|
||||
rv = aKey->ReadStringValue(NS_LITERAL_STRING("SMTP Server"), smtpServer);
|
||||
SetSmtpServer(smtpServer, aKey, id, aIncomgUserName, authMethodIncoming);
|
||||
}
|
||||
|
||||
void OESettings::SetSmtpServer(const nsString &aSmtpServer,
|
||||
nsIWindowsRegKey *aKey,
|
||||
nsIMsgIdentity *aId,
|
||||
const nsString &aIncomgUserName,
|
||||
int32_t authMethodIncoming)
|
||||
{
|
||||
// set the id.smtpserver accordingly
|
||||
// first we have to calculate the smtp user name which is based on sicily
|
||||
if (!aKey || !aId || aIncomgUserName.IsEmpty() || aSmtpServer.IsEmpty())
|
||||
return;
|
||||
nsCString smtpServerKey;
|
||||
// smtp user name depends on sicily which may or not exist
|
||||
uint32_t useSicily = 0;
|
||||
nsresult rv = aKey->ReadIntValue(NS_LITERAL_STRING("SMTP Use Sicily"),
|
||||
&useSicily);
|
||||
nsAutoString userName;
|
||||
switch (useSicily) {
|
||||
case 1:
|
||||
case 3:
|
||||
// has to go in whether empty or no
|
||||
// shouldn't be empty but better safe than sorry
|
||||
aKey->ReadStringValue(NS_LITERAL_STRING("SMTP User Name"), userName);
|
||||
break;
|
||||
case 2:
|
||||
userName = aIncomgUserName;
|
||||
break;
|
||||
default:
|
||||
break; // initial userName == ""
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISmtpService> smtpService(do_GetService(NS_SMTPSERVICE_CONTRACTID, &rv));
|
||||
if (NS_SUCCEEDED(rv) && smtpService) {
|
||||
nsCOMPtr<nsISmtpServer> foundServer;
|
||||
// don't try to make another server
|
||||
// regardless if username doesn't match
|
||||
nsAutoCString nativeUserName;
|
||||
NS_CopyUnicodeToNative(userName, nativeUserName);
|
||||
nsAutoCString nativeSmtpServer;
|
||||
NS_CopyUnicodeToNative(aSmtpServer, nativeSmtpServer);
|
||||
rv = smtpService->FindServer(nativeUserName.get(),
|
||||
nativeSmtpServer.get(),
|
||||
getter_AddRefs(foundServer));
|
||||
if (NS_SUCCEEDED(rv) && foundServer) {
|
||||
// set our account keyed to this smptserver key
|
||||
foundServer->GetKey(getter_Copies(smtpServerKey));
|
||||
aId->SetSmtpServerKey(smtpServerKey);
|
||||
|
||||
IMPORT_LOG1("SMTP server already exists: %s\n",
|
||||
nativeSmtpServer.get());
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsISmtpServer> smtpServer;
|
||||
rv = smtpService->CreateServer(getter_AddRefs(smtpServer));
|
||||
if (NS_SUCCEEDED(rv) && smtpServer) {
|
||||
uint32_t port = 0;
|
||||
rv = aKey->ReadIntValue(NS_LITERAL_STRING("SMTP Port"),
|
||||
&port);
|
||||
if (NS_SUCCEEDED(rv) && port)
|
||||
smtpServer->SetPort(static_cast<int32_t>(port));
|
||||
|
||||
int32_t socketType = nsMsgSocketType::plain;
|
||||
uint32_t secureConnection = 0;
|
||||
rv = aKey->ReadIntValue(NS_LITERAL_STRING("SMTP Secure Connection"),
|
||||
&secureConnection);
|
||||
if (NS_SUCCEEDED(rv) && secureConnection == 1) {
|
||||
// Outlook Express does not support STARTTLS without KB933612 fix.
|
||||
if (IsKB933612Applied() && port != 465)
|
||||
socketType = nsMsgSocketType::alwaysSTARTTLS;
|
||||
else
|
||||
socketType = nsMsgSocketType::SSL;
|
||||
}
|
||||
smtpServer->SetSocketType(socketType);
|
||||
smtpServer->SetUsername(nativeUserName);
|
||||
switch (useSicily) {
|
||||
case 1 :
|
||||
smtpServer->SetAuthMethod(nsMsgAuthMethod::secure);
|
||||
break;
|
||||
case 2 : // requires SMTP authentication to use the incoming server settings
|
||||
smtpServer->SetAuthMethod(authMethodIncoming);
|
||||
break;
|
||||
case 3 :
|
||||
smtpServer->SetAuthMethod(nsMsgAuthMethod::passwordCleartext);
|
||||
break;
|
||||
default:
|
||||
smtpServer->SetAuthMethod(nsMsgAuthMethod::none);
|
||||
}
|
||||
|
||||
smtpServer->SetHostname(nativeSmtpServer);
|
||||
|
||||
smtpServer->GetKey(getter_Copies(smtpServerKey));
|
||||
aId->SetSmtpServerKey(smtpServerKey);
|
||||
|
||||
IMPORT_LOG1("Created new SMTP server: %s\n",
|
||||
nativeSmtpServer.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool OESettings::IsKB933612Applied()
|
||||
{
|
||||
// The following versions of Windows include KB933612 fix:
|
||||
// - Windows 7 and future versions of Windows
|
||||
// - Windows Vista, SP1 or later
|
||||
// - Windows Server 2003, SP2 or later
|
||||
// - Windows XP, SP3 or later
|
||||
//
|
||||
// The following versions do not:
|
||||
// - Windows Vista SP0
|
||||
// - Windows Server 2003, SP1 or earlier
|
||||
// - Windows XP, SP2 or earlier
|
||||
//
|
||||
// See http://support.microsoft.com/kb/929123 and
|
||||
// http://support.microsoft.com/kb/933612
|
||||
//
|
||||
// Note that mozilla::IsWin2003SP2OrLater() will return true for
|
||||
// Windows Vista and mozilla::IsXPSP3OrLater() will return true
|
||||
// for Windows Server 2003.
|
||||
return mozilla::IsVistaSP1OrLater() ||
|
||||
!mozilla::IsWin2003OrLater() && mozilla::IsXPSP3OrLater() ||
|
||||
!mozilla::IsVistaOrLater() && mozilla::IsWin2003SP2OrLater();
|
||||
}
|
||||
|
||||
22
mailnews/import/oexpress/nsOESettings.h
Normal file
22
mailnews/import/oexpress/nsOESettings.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#ifndef nsOESettings_h___
|
||||
#define nsOESettings_h___
|
||||
|
||||
#include "nsIImportSettings.h"
|
||||
|
||||
class nsOESettings : public nsIImportSettings {
|
||||
public:
|
||||
nsOESettings();
|
||||
static nsresult Create(nsIImportSettings** aImport);
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIIMPORTSETTINGS
|
||||
|
||||
private:
|
||||
virtual ~nsOESettings();
|
||||
};
|
||||
|
||||
#endif /* nsOESettings_h___ */
|
||||
71
mailnews/import/oexpress/nsOEStringBundle.cpp
Normal file
71
mailnews/import/oexpress/nsOEStringBundle.cpp
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/* -*- 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 "prprf.h"
|
||||
#include "prmem.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsOEStringBundle.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIURI.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
#define OE_MSGS_URL "chrome://messenger/locale/oeImportMsgs.properties"
|
||||
|
||||
nsIStringBundle * nsOEStringBundle::m_pBundle = nullptr;
|
||||
|
||||
nsIStringBundle *nsOEStringBundle::GetStringBundle(void)
|
||||
{
|
||||
if (m_pBundle)
|
||||
return m_pBundle;
|
||||
|
||||
char* propertyURL = OE_MSGS_URL;
|
||||
nsIStringBundle* sBundle = nullptr;
|
||||
|
||||
nsCOMPtr<nsIStringBundleService> sBundleService =
|
||||
mozilla::services::GetStringBundleService();
|
||||
if (sBundleService) {
|
||||
sBundleService->CreateBundle(propertyURL, &sBundle);
|
||||
}
|
||||
|
||||
m_pBundle = sBundle;
|
||||
|
||||
return sBundle;
|
||||
}
|
||||
|
||||
|
||||
void nsOEStringBundle::GetStringByID(int32_t stringID, nsString& result)
|
||||
{
|
||||
char16_t *ptrv = GetStringByID(stringID);
|
||||
result.Adopt(ptrv);
|
||||
}
|
||||
|
||||
char16_t *nsOEStringBundle::GetStringByID(int32_t stringID)
|
||||
{
|
||||
if (!m_pBundle)
|
||||
m_pBundle = GetStringBundle();
|
||||
|
||||
if (m_pBundle) {
|
||||
char16_t *ptrv = nullptr;
|
||||
nsresult rv = m_pBundle->GetStringFromID(stringID, &ptrv);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && ptrv)
|
||||
return ptrv;
|
||||
}
|
||||
|
||||
nsString resultString;
|
||||
resultString.AppendLiteral("[StringID ");
|
||||
resultString.AppendInt(stringID);
|
||||
resultString.AppendLiteral("?]");
|
||||
|
||||
return ToNewUnicode(resultString);
|
||||
}
|
||||
|
||||
void nsOEStringBundle::Cleanup(void)
|
||||
{
|
||||
if (m_pBundle)
|
||||
m_pBundle->Release();
|
||||
m_pBundle = nullptr;
|
||||
}
|
||||
38
mailnews/import/oexpress/nsOEStringBundle.h
Normal file
38
mailnews/import/oexpress/nsOEStringBundle.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/* 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 _nsOEStringBundle_H__
|
||||
#define _nsOEStringBundle_H__
|
||||
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
class nsIStringBundle;
|
||||
|
||||
class nsOEStringBundle {
|
||||
public:
|
||||
static char16_t * GetStringByID(int32_t stringID);
|
||||
static void GetStringByID(int32_t stringID, nsString& result);
|
||||
static nsIStringBundle * GetStringBundle(void); // don't release
|
||||
static void FreeString(char16_t *pStr) { NS_Free(pStr);}
|
||||
static void Cleanup(void);
|
||||
|
||||
private:
|
||||
static nsIStringBundle * m_pBundle;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define OEIMPORT_NAME 2000
|
||||
#define OEIMPORT_DESCRIPTION 2011
|
||||
#define OEIMPORT_MAILBOX_SUCCESS 2002
|
||||
#define OEIMPORT_MAILBOX_BADPARAM 2003
|
||||
#define OEIMPORT_MAILBOX_BADSOURCEFILE 2004
|
||||
#define OEIMPORT_MAILBOX_CONVERTERROR 2005
|
||||
#define OEIMPORT_DEFAULT_NAME 2006
|
||||
#define OEIMPORT_AUTOFIND 2007
|
||||
#define OEIMPORT_ADDRESS_SUCCESS 2008
|
||||
#define OEIMPORT_ADDRESS_CONVERTERROR 2009
|
||||
#define OEIMPORT_ADDRESS_BADPARAM 2010
|
||||
|
||||
#endif /* _nsOEStringBundle_H__ */
|
||||
Loading…
Add table
Add a link
Reference in a new issue