зеркало из https://github.com/mozilla/pjs.git
make outlook express imported e-mails have x-mozilla-status lines so summary file regeneration won't lose read state, 223679, r/sr=mscott
This commit is contained in:
Родитель
9a45c49e29
Коммит
e28f0bda7e
|
@ -39,6 +39,9 @@
|
|||
#include "nsCRT.h"
|
||||
#include "OEDebugLog.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "msgCore.h"
|
||||
#include "prprf.h"
|
||||
#include "nsMsgLocalFolderHdrs.h"
|
||||
|
||||
|
||||
#define kIndexGrowBy 100
|
||||
|
@ -98,51 +101,51 @@ PRBool nsOE5File::IsLocalMailFile( nsIFileSpec *pFile)
|
|||
|
||||
PRBool nsOE5File::ReadIndex( nsIFileSpec *pFile, PRUint32 **ppIndex, PRUint32 *pSize)
|
||||
{
|
||||
*ppIndex = nsnull;
|
||||
*pSize = 0;
|
||||
|
||||
char signature[4];
|
||||
if (!ReadBytes( pFile, signature, 0, 4))
|
||||
return( PR_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( PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
PRUint32 offset = 0x00e4;
|
||||
PRUint32 indexStart = 0;
|
||||
if (!ReadBytes( pFile, &indexStart, offset, 4)) {
|
||||
IMPORT_LOG0( "*** Unable to read offset to index start\n");
|
||||
return( PR_FALSE);
|
||||
}
|
||||
|
||||
PRUint32Array array;
|
||||
array.count = 0;
|
||||
array.alloc = kIndexGrowBy;
|
||||
array.pIndex = new PRUint32[kIndexGrowBy];
|
||||
|
||||
PRUint32 next = ReadMsgIndex( pFile, indexStart, &array);
|
||||
while (next) {
|
||||
next = ReadMsgIndex( pFile, next, &array);
|
||||
}
|
||||
|
||||
if (array.count) {
|
||||
*pSize = array.count;
|
||||
*ppIndex = array.pIndex;
|
||||
return( PR_TRUE);
|
||||
}
|
||||
|
||||
delete [] array.pIndex;
|
||||
return( PR_FALSE);
|
||||
*ppIndex = nsnull;
|
||||
*pSize = 0;
|
||||
|
||||
char signature[4];
|
||||
if (!ReadBytes( pFile, signature, 0, 4))
|
||||
return( PR_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( PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
PRUint32 offset = 0x00e4;
|
||||
PRUint32 indexStart = 0;
|
||||
if (!ReadBytes( pFile, &indexStart, offset, 4)) {
|
||||
IMPORT_LOG0( "*** Unable to read offset to index start\n");
|
||||
return( PR_FALSE);
|
||||
}
|
||||
|
||||
PRUint32Array array;
|
||||
array.count = 0;
|
||||
array.alloc = kIndexGrowBy;
|
||||
array.pIndex = new PRUint32[kIndexGrowBy];
|
||||
|
||||
PRUint32 next = ReadMsgIndex( pFile, indexStart, &array);
|
||||
while (next) {
|
||||
next = ReadMsgIndex( pFile, next, &array);
|
||||
}
|
||||
|
||||
if (array.count) {
|
||||
*pSize = array.count;
|
||||
*ppIndex = array.pIndex;
|
||||
return( PR_TRUE);
|
||||
}
|
||||
|
||||
delete [] array.pIndex;
|
||||
return( PR_FALSE);
|
||||
}
|
||||
|
||||
|
||||
PRUint32 nsOE5File::ReadMsgIndex( nsIFileSpec *file, PRUint32 offset, PRUint32Array *pArray)
|
||||
{
|
||||
// Record is:
|
||||
// Record is:
|
||||
// 4 byte marker
|
||||
// 4 byte unknown
|
||||
// 4 byte nextSubIndex
|
||||
|
@ -152,85 +155,80 @@ PRUint32 nsOE5File::ReadMsgIndex( nsIFileSpec *file, PRUint32 offset, PRUint32Ar
|
|||
// 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
|
||||
|
||||
PRUint32 marker;
|
||||
|
||||
if (!ReadBytes( file, &marker, offset, 4))
|
||||
return( 0);
|
||||
|
||||
if (marker != offset)
|
||||
return( 0);
|
||||
|
||||
|
||||
PRUint32 vals[3];
|
||||
|
||||
if (!ReadBytes( file, vals, offset + 4, 12))
|
||||
return( 0);
|
||||
|
||||
|
||||
PRUint8 len[4];
|
||||
if (!ReadBytes( file, len, offset + 16, 4))
|
||||
return( 0);
|
||||
|
||||
|
||||
|
||||
PRUint32 cnt = (PRUint32) len[1];
|
||||
cnt *= 3;
|
||||
PRUint32 *pData = new PRUint32[cnt];
|
||||
|
||||
if (!ReadBytes( file, pData, offset + 24, cnt * 4)) {
|
||||
delete [] pData;
|
||||
return( 0);
|
||||
}
|
||||
|
||||
PRUint32 next;
|
||||
PRUint32 indexOffset;
|
||||
PRUint32 * pRecord = pData;
|
||||
PRUint32 * pNewIndex;
|
||||
|
||||
for (PRUint8 i = 0; i < (PRUint8)len[1]; i++, pRecord += 3) {
|
||||
indexOffset = pRecord[0];
|
||||
|
||||
if (pArray->count >= pArray->alloc) {
|
||||
pNewIndex = new PRUint32[ 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( file, next, pArray)) != 0);
|
||||
}
|
||||
delete pData;
|
||||
|
||||
// return the pointer to the next subIndex
|
||||
return( vals[1]);
|
||||
// 1 - pointer to record
|
||||
// 2 - child index pointer
|
||||
// 3 - number of records in child
|
||||
|
||||
PRUint32 marker;
|
||||
|
||||
if (!ReadBytes( file, &marker, offset, 4))
|
||||
return( 0);
|
||||
|
||||
if (marker != offset)
|
||||
return( 0);
|
||||
|
||||
|
||||
PRUint32 vals[3];
|
||||
|
||||
if (!ReadBytes( file, vals, offset + 4, 12))
|
||||
return( 0);
|
||||
|
||||
|
||||
PRUint8 len[4];
|
||||
if (!ReadBytes( file, len, offset + 16, 4))
|
||||
return( 0);
|
||||
|
||||
|
||||
|
||||
PRUint32 cnt = (PRUint32) len[1];
|
||||
cnt *= 3;
|
||||
PRUint32 *pData = new PRUint32[cnt];
|
||||
|
||||
if (!ReadBytes( file, pData, offset + 24, cnt * 4)) {
|
||||
delete [] pData;
|
||||
return( 0);
|
||||
}
|
||||
|
||||
PRUint32 next;
|
||||
PRUint32 indexOffset;
|
||||
PRUint32 * pRecord = pData;
|
||||
PRUint32 * pNewIndex;
|
||||
|
||||
for (PRUint8 i = 0; i < (PRUint8)len[1]; i++, pRecord += 3) {
|
||||
indexOffset = pRecord[0];
|
||||
|
||||
if (pArray->count >= pArray->alloc) {
|
||||
pNewIndex = new PRUint32[ 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( file, next, pArray)) != 0);
|
||||
}
|
||||
delete pData;
|
||||
|
||||
// return the pointer to the next subIndex
|
||||
return( vals[1]);
|
||||
}
|
||||
|
||||
PRBool nsOE5File::IsFromLine( char *pLine, PRUint32 len)
|
||||
{
|
||||
if (len >= 5) {
|
||||
if ( (*pLine == 'F') && (pLine[1] = 'r') && (pLine[2] == 'o') && (pLine[3] == 'm') && (pLine[4] == ' '))
|
||||
return( PR_TRUE);
|
||||
}
|
||||
|
||||
return( PR_FALSE);
|
||||
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!
|
||||
|
@ -239,85 +237,85 @@ const char *nsOE5File::m_pFromLineSep = "From - Mon Jan 1 00:00:00 1965\x0D\x0A"
|
|||
|
||||
nsresult nsOE5File::ImportMailbox( PRUint32 *pBytesDone, PRBool *pAbort, nsString& name, nsIFileSpec *inFile, nsIFileSpec *pDestination, PRUint32 *pCount)
|
||||
{
|
||||
nsresult rv;
|
||||
PRInt32 msgCount = 0;
|
||||
if (pCount)
|
||||
*pCount = 0;
|
||||
|
||||
rv = inFile->OpenStreamForReading();
|
||||
if (NS_FAILED( rv)) return( rv);
|
||||
rv = pDestination->OpenStreamForWriting();
|
||||
if (NS_FAILED( rv)) {
|
||||
inFile->CloseStream();
|
||||
return( rv);
|
||||
}
|
||||
|
||||
PRUint32 * pIndex;
|
||||
PRUint32 indexSize;
|
||||
|
||||
if (!ReadIndex( inFile, &pIndex, &indexSize)) {
|
||||
IMPORT_LOG1( "No messages found in mailbox: %S\n", name.get());
|
||||
inFile->CloseStream();
|
||||
pDestination->CloseStream();
|
||||
return( NS_OK);
|
||||
}
|
||||
|
||||
char * pBuffer = new char[kMailboxBufferSize];
|
||||
if (!(*pAbort))
|
||||
ConvertIndex( inFile, pBuffer, pIndex, indexSize);
|
||||
|
||||
PRUint32 block[4];
|
||||
PRInt32 sepLen = (PRInt32) strlen( m_pFromLineSep);
|
||||
PRInt32 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:
|
||||
nsresult rv;
|
||||
PRInt32 msgCount = 0;
|
||||
if (pCount)
|
||||
*pCount = 0;
|
||||
|
||||
rv = inFile->OpenStreamForReading();
|
||||
if (NS_FAILED( rv)) return( rv);
|
||||
rv = pDestination->OpenStreamForWriting();
|
||||
if (NS_FAILED( rv)) {
|
||||
inFile->CloseStream();
|
||||
return( rv);
|
||||
}
|
||||
|
||||
PRUint32 * pIndex;
|
||||
PRUint32 indexSize;
|
||||
|
||||
if (!ReadIndex( inFile, &pIndex, &indexSize)) {
|
||||
IMPORT_LOG1( "No messages found in mailbox: %S\n", name.get());
|
||||
inFile->CloseStream();
|
||||
pDestination->CloseStream();
|
||||
return( NS_OK);
|
||||
}
|
||||
|
||||
char * pBuffer = new char[kMailboxBufferSize];
|
||||
if (!(*pAbort))
|
||||
ConvertIndex( inFile, pBuffer, pIndex, indexSize);
|
||||
|
||||
PRUint32 block[4];
|
||||
PRInt32 sepLen = (PRInt32) strlen( m_pFromLineSep);
|
||||
PRInt32 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.
|
||||
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).
|
||||
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.
|
||||
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.
|
||||
*/
|
||||
|
||||
PRUint32 didBytes = 0;
|
||||
*/
|
||||
|
||||
PRUint32 didBytes = 0;
|
||||
PRUint32 next, size;
|
||||
char *pStart, *pEnd, *partialLineStart;
|
||||
nsCAutoString partialLine, tempLine;
|
||||
rv = NS_OK;
|
||||
|
||||
rv = NS_OK;
|
||||
|
||||
for (PRUint32 i = 0; (i < indexSize) && !(*pAbort); i++)
|
||||
{
|
||||
if (! pIndex[i])
|
||||
continue;
|
||||
|
||||
|
||||
if (ReadBytes( inFile, block, pIndex[i], 16) && (block[0] == pIndex[i]) &&
|
||||
(block[2] < kMailboxBufferSize) && (ReadBytes( inFile, pBuffer, kDontSeek, block[2])))
|
||||
(block[2] < kMailboxBufferSize) && (ReadBytes( inFile, 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.
|
||||
|
||||
// write out the from separator.
|
||||
if (IsFromLine( pBuffer, size))
|
||||
{
|
||||
char *pChar = pStart;
|
||||
while ((pChar < pEnd) && (*pChar != nsCRT::CR) && (*(pChar+1) != nsCRT::LF))
|
||||
pChar++;
|
||||
|
||||
|
||||
if (pChar < pEnd)
|
||||
{
|
||||
// Get the "From " line so write it out.
|
||||
|
@ -330,36 +328,45 @@ nsresult nsOE5File::ImportMailbox( PRUint32 *pBytesDone, PRBool *pAbort, nsStrin
|
|||
else
|
||||
{
|
||||
// Write out the default from line since there is none in the msg.
|
||||
rv = pDestination->Write( m_pFromLineSep, sepLen, &written);
|
||||
// FIXME: Do I need to check the return value of written???
|
||||
if (NS_FAILED( rv))
|
||||
break;
|
||||
}
|
||||
rv = pDestination->Write( m_pFromLineSep, sepLen, &written);
|
||||
// FIXME: Do I need to check the return value of written???
|
||||
if (NS_FAILED( rv))
|
||||
break;
|
||||
}
|
||||
|
||||
char statusLine[50];
|
||||
PRUint32 msgFlags = 0; // need to convert from OE flags to mozilla flags
|
||||
PR_snprintf(statusLine, sizeof(statusLine), X_MOZILLA_STATUS_FORMAT MSG_LINEBREAK, msgFlags & 0xFFFF);
|
||||
rv = pDestination->Write(statusLine, strlen(statusLine), &written);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
PR_snprintf(statusLine, sizeof(statusLine), X_MOZILLA_STATUS2_FORMAT MSG_LINEBREAK, msgFlags & 0xFFFF0000);
|
||||
rv = pDestination->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) == nsCRT::CR && *(pEnd - 1) == nsCRT::LF) )
|
||||
{
|
||||
partialLineStart -= 2;
|
||||
while ((partialLineStart >= pStart) && (*partialLineStart != nsCRT::CR) && (*(partialLineStart+1) != nsCRT::LF))
|
||||
while ((partialLineStart >= pStart) && (*partialLineStart != nsCRT::CR) && (*(partialLineStart+1) != nsCRT::LF))
|
||||
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(pDestination, pStart, partialLineStart);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
|
||||
didBytes += block[2];
|
||||
|
||||
|
||||
next = block[3];
|
||||
if (! next)
|
||||
{
|
||||
|
@ -368,38 +375,38 @@ nsresult nsOE5File::ImportMailbox( PRUint32 *pBytesDone, PRBool *pAbort, nsStrin
|
|||
rv = EscapeFromSpaceLine(pDestination, (char *)partialLine.get(), (partialLine.get()+partialLine.Length()));
|
||||
}
|
||||
else
|
||||
if (ReadBytes(inFile, block, next, 16) && (block[0] == next) &&
|
||||
if (ReadBytes(inFile, block, next, 16) && (block[0] == next) &&
|
||||
(block[2] < kMailboxBufferSize) && (ReadBytes(inFile, 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 != nsCRT::CR) && (*(pStart+1) != nsCRT::LF))
|
||||
pStart++;
|
||||
tempLine.Assign(pBuffer, pStart - pBuffer + 2);
|
||||
partialLine.Append(tempLine);
|
||||
rv = EscapeFromSpaceLine(pDestination, (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 + 2);
|
||||
pStart += 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 != nsCRT::CR) && (*(pStart+1) != nsCRT::LF))
|
||||
pStart++;
|
||||
tempLine.Assign(pBuffer, pStart - pBuffer + 2);
|
||||
partialLine.Append(tempLine);
|
||||
rv = EscapeFromSpaceLine(pDestination, (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 + 2);
|
||||
pStart += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IMPORT_LOG2( "Error reading message from %S at 0x%lx\n", name.get(), pIndex[i]);
|
||||
rv = pDestination->Write( "\x0D\x0A", 2, &written);
|
||||
next = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IMPORT_LOG2( "Error reading message from %S at 0x%lx\n", name.get(), pIndex[i]);
|
||||
rv = pDestination->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:
|
||||
|
@ -415,127 +422,135 @@ nsresult nsOE5File::ImportMailbox( PRUint32 *pBytesDone, PRBool *pAbort, nsStrin
|
|||
// In this case, the 1st msg is not recognized as a msg (it's skipped)
|
||||
// when you open the folder.
|
||||
rv = pDestination->Write( "\x0D\x0A", 2, &written);
|
||||
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
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", name.get(), pIndex[i]);
|
||||
|
||||
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", name.get(), pIndex[i]);
|
||||
*pAbort = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
delete [] pBuffer;
|
||||
inFile->CloseStream();
|
||||
pDestination->CloseStream();
|
||||
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
*pAbort = PR_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 unknown
|
||||
1 bytes - number of attributes
|
||||
1 byte unknown
|
||||
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.
|
||||
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
|
||||
(2 bytes - flag offset in msg hdr?) or the following?
|
||||
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.
|
||||
|
||||
Current known tags are:
|
||||
0x02 - a time value
|
||||
0x04 - text offset pointer, the data is the offset after the attribute
|
||||
of a 4 byte pointer to the message text
|
||||
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
|
||||
0x80 - msgId
|
||||
0x84 - direct text offset, direct pointer to message text
|
||||
|
||||
flags we're interested in:
|
||||
kMarked= 0x20;
|
||||
kRead = 0x80;
|
||||
kHasAttachment = 0x4000;
|
||||
kIsReply= 0x80000;
|
||||
|
||||
Current known tags are:
|
||||
0x02 - a time value
|
||||
0x04 - text offset pointer, the data is the offset after the attribute
|
||||
of a 4 byte pointer to the message text
|
||||
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
|
||||
0x80 - msgId
|
||||
0x84 - direct text offset, direct pointer to message text
|
||||
*/
|
||||
|
||||
|
||||
void nsOE5File::ConvertIndex( nsIFileSpec *pFile, char *pBuffer, PRUint32 *pIndex, PRUint32 size)
|
||||
{
|
||||
// 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.
|
||||
|
||||
PRUint8 recordHead[12];
|
||||
PRUint32 marker;
|
||||
PRUint32 recordSize;
|
||||
PRUint32 numAttrs;
|
||||
PRUint32 offset;
|
||||
PRUint32 attrIndex;
|
||||
PRUint32 attrOffset;
|
||||
PRUint8 tag;
|
||||
PRUint32 tagData;
|
||||
|
||||
for (PRUint32 i = 0; i < size; i++) {
|
||||
offset = 0;
|
||||
if (ReadBytes( pFile, recordHead, pIndex[i], 12)) {
|
||||
memcpy( &marker, recordHead, 4);
|
||||
memcpy( &recordSize, recordHead + 4, 4);
|
||||
numAttrs = (PRUint32) recordHead[10];
|
||||
if ((marker == pIndex[i]) && (recordSize < kMailboxBufferSize) && ((numAttrs * 4) <= recordSize)) {
|
||||
if (ReadBytes( pFile, pBuffer, kDontSeek, recordSize)) {
|
||||
attrOffset = 0;
|
||||
for (attrIndex = 0; attrIndex < numAttrs; attrIndex++, attrOffset += 4) {
|
||||
tag = (PRUint8) pBuffer[attrOffset];
|
||||
if (tag == (PRUint8) 0x84) {
|
||||
tagData = 0;
|
||||
memcpy( &tagData, pBuffer + attrOffset + 1, 3);
|
||||
offset = tagData;
|
||||
break;
|
||||
}
|
||||
else if (tag == (PRUint8) 0x04) {
|
||||
tagData = 0;
|
||||
memcpy( &tagData, pBuffer + attrOffset + 1, 3);
|
||||
if (((numAttrs * 4) + tagData + 4) <= recordSize)
|
||||
memcpy( &offset, pBuffer + (numAttrs * 4) + tagData, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pIndex[i] = offset;
|
||||
}
|
||||
// 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.
|
||||
|
||||
PRUint8 recordHead[12];
|
||||
PRUint32 marker;
|
||||
PRUint32 recordSize;
|
||||
PRUint32 numAttrs;
|
||||
PRUint32 offset;
|
||||
PRUint32 attrIndex;
|
||||
PRUint32 attrOffset;
|
||||
PRUint8 tag;
|
||||
PRUint32 tagData;
|
||||
|
||||
for (PRUint32 i = 0; i < size; i++) {
|
||||
offset = 0;
|
||||
if (ReadBytes( pFile, recordHead, pIndex[i], 12)) {
|
||||
memcpy( &marker, recordHead, 4);
|
||||
memcpy( &recordSize, recordHead + 4, 4);
|
||||
numAttrs = (PRUint32) recordHead[10];
|
||||
if ((marker == pIndex[i]) && (recordSize < kMailboxBufferSize) && ((numAttrs * 4) <= recordSize)) {
|
||||
if (ReadBytes( pFile, pBuffer, kDontSeek, recordSize)) {
|
||||
attrOffset = 0;
|
||||
for (attrIndex = 0; attrIndex < numAttrs; attrIndex++, attrOffset += 4) {
|
||||
tag = (PRUint8) pBuffer[attrOffset];
|
||||
if (tag == (PRUint8) 0x84) {
|
||||
tagData = 0;
|
||||
memcpy( &tagData, pBuffer + attrOffset + 1, 3);
|
||||
offset = tagData;
|
||||
break;
|
||||
}
|
||||
else if (tag == (PRUint8) 0x04) {
|
||||
tagData = 0;
|
||||
memcpy( &tagData, pBuffer + attrOffset + 1, 3);
|
||||
if (((numAttrs * 4) + tagData + 4) <= recordSize)
|
||||
memcpy( &offset, pBuffer + (numAttrs * 4) + tagData, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pIndex[i] = offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PRBool nsOE5File::ReadBytes( nsIFileSpec *stream, void *pBuffer, PRUint32 offset, PRUint32 bytes)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (offset != kDontSeek) {
|
||||
rv = stream->Seek( offset);
|
||||
if (NS_FAILED( rv))
|
||||
return( PR_FALSE);
|
||||
}
|
||||
|
||||
if (!bytes)
|
||||
return( PR_TRUE);
|
||||
|
||||
PRInt32 cntRead;
|
||||
char * pReadTo = (char *)pBuffer;
|
||||
rv = stream->Read( &pReadTo, bytes, &cntRead);
|
||||
if (NS_FAILED( rv) || ((PRUint32)cntRead != bytes))
|
||||
return( PR_FALSE);
|
||||
return( PR_TRUE);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (offset != kDontSeek) {
|
||||
rv = stream->Seek( offset);
|
||||
if (NS_FAILED( rv))
|
||||
return( PR_FALSE);
|
||||
}
|
||||
|
||||
if (!bytes)
|
||||
return( PR_TRUE);
|
||||
|
||||
PRInt32 cntRead;
|
||||
char * pReadTo = (char *)pBuffer;
|
||||
rv = stream->Read( &pReadTo, bytes, &cntRead);
|
||||
if (NS_FAILED( rv) || ((PRUint32)cntRead != bytes))
|
||||
return( PR_FALSE);
|
||||
return( PR_TRUE);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -444,81 +444,81 @@ void ImportOEMailImpl::SetLogs( nsString& success, nsString& error, PRUnichar **
|
|||
}
|
||||
|
||||
NS_IMETHODIMP ImportOEMailImpl::ImportMailbox( nsIImportMailboxDescriptor *pSource,
|
||||
nsIFileSpec *pDestination,
|
||||
PRUnichar **pErrorLog,
|
||||
PRUnichar **pSuccessLog,
|
||||
PRBool *fatalError)
|
||||
nsIFileSpec *pDestination,
|
||||
PRUnichar **pErrorLog,
|
||||
PRUnichar **pSuccessLog,
|
||||
PRBool *fatalError)
|
||||
{
|
||||
NS_PRECONDITION(pSource != nsnull, "null ptr");
|
||||
NS_PRECONDITION(pDestination != nsnull, "null ptr");
|
||||
NS_PRECONDITION(fatalError != nsnull, "null ptr");
|
||||
|
||||
nsCOMPtr<nsIStringBundle> bundle( dont_AddRef( nsOEStringBundle::GetStringBundleProxy()));
|
||||
|
||||
nsString success;
|
||||
nsString error;
|
||||
if (!pSource || !pDestination || !fatalError) {
|
||||
nsOEStringBundle::GetStringByID( OEIMPORT_MAILBOX_BADPARAM, error, bundle);
|
||||
if (fatalError)
|
||||
*fatalError = PR_TRUE;
|
||||
SetLogs( success, error, pErrorLog, pSuccessLog);
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
PRBool abort = PR_FALSE;
|
||||
nsString name;
|
||||
nsXPIDLString pName;
|
||||
if (NS_SUCCEEDED( pSource->GetDisplayName( getter_Copies(pName)))) {
|
||||
name = pName;
|
||||
}
|
||||
|
||||
PRUint32 mailSize = 0;
|
||||
pSource->GetSize( &mailSize);
|
||||
if (mailSize == 0) {
|
||||
ReportSuccess( name, 0, &success);
|
||||
SetLogs( success, error, pErrorLog, pSuccessLog);
|
||||
return( NS_OK);
|
||||
}
|
||||
|
||||
nsIFileSpec * inFile;
|
||||
if (NS_FAILED( pSource->GetFileSpec( &inFile))) {
|
||||
ReportError( OEIMPORT_MAILBOX_BADSOURCEFILE, name, &error);
|
||||
SetLogs( success, error, pErrorLog, pSuccessLog);
|
||||
return( NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
NS_PRECONDITION(pSource != nsnull, "null ptr");
|
||||
NS_PRECONDITION(pDestination != nsnull, "null ptr");
|
||||
NS_PRECONDITION(fatalError != nsnull, "null ptr");
|
||||
|
||||
nsCOMPtr<nsIStringBundle> bundle( dont_AddRef( nsOEStringBundle::GetStringBundleProxy()));
|
||||
|
||||
nsString success;
|
||||
nsString error;
|
||||
if (!pSource || !pDestination || !fatalError) {
|
||||
nsOEStringBundle::GetStringByID( OEIMPORT_MAILBOX_BADPARAM, error, bundle);
|
||||
if (fatalError)
|
||||
*fatalError = PR_TRUE;
|
||||
SetLogs( success, error, pErrorLog, pSuccessLog);
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
PRBool abort = PR_FALSE;
|
||||
nsString name;
|
||||
nsXPIDLString pName;
|
||||
if (NS_SUCCEEDED( pSource->GetDisplayName( getter_Copies(pName)))) {
|
||||
name = pName;
|
||||
}
|
||||
|
||||
PRUint32 mailSize = 0;
|
||||
pSource->GetSize( &mailSize);
|
||||
if (mailSize == 0) {
|
||||
ReportSuccess( name, 0, &success);
|
||||
SetLogs( success, error, pErrorLog, pSuccessLog);
|
||||
return( NS_OK);
|
||||
}
|
||||
|
||||
nsIFileSpec * inFile;
|
||||
if (NS_FAILED( pSource->GetFileSpec( &inFile))) {
|
||||
ReportError( OEIMPORT_MAILBOX_BADSOURCEFILE, name, &error);
|
||||
SetLogs( success, error, pErrorLog, pSuccessLog);
|
||||
return( NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
nsXPIDLCString pPath;
|
||||
inFile->GetNativePath(getter_Copies(pPath));
|
||||
IMPORT_LOG1( "Importing Outlook Express mailbox: %s\n", pPath.get());
|
||||
|
||||
m_bytesDone = 0;
|
||||
PRUint32 msgCount = 0;
|
||||
nsresult rv;
|
||||
if (nsOE5File::IsLocalMailFile( inFile)) {
|
||||
IMPORT_LOG1( "Importing OE5 mailbox: %S!\n", name.get());
|
||||
rv = nsOE5File::ImportMailbox( &m_bytesDone, &abort, name, inFile, pDestination, &msgCount);
|
||||
}
|
||||
else {
|
||||
if (CImportMailbox::ImportMailbox( &m_bytesDone, &abort, name, inFile, pDestination, &msgCount)) {
|
||||
IMPORT_LOG1( "Importing Outlook Express mailbox: %s\n", pPath.get());
|
||||
|
||||
m_bytesDone = 0;
|
||||
PRUint32 msgCount = 0;
|
||||
nsresult rv;
|
||||
if (nsOE5File::IsLocalMailFile( inFile)) {
|
||||
IMPORT_LOG1( "Importing OE5 mailbox: %S!\n", name.get());
|
||||
rv = nsOE5File::ImportMailbox( &m_bytesDone, &abort, name, inFile, pDestination, &msgCount);
|
||||
}
|
||||
else {
|
||||
if (CImportMailbox::ImportMailbox( &m_bytesDone, &abort, name, inFile, pDestination, &msgCount)) {
|
||||
rv = NS_OK;
|
||||
}
|
||||
else {
|
||||
}
|
||||
else {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
inFile->Release();
|
||||
|
||||
if (NS_SUCCEEDED( rv)) {
|
||||
ReportSuccess( name, msgCount, &success);
|
||||
}
|
||||
else {
|
||||
ReportError( OEIMPORT_MAILBOX_CONVERTERROR, name, &error);
|
||||
}
|
||||
|
||||
SetLogs( success, error, pErrorLog, pSuccessLog);
|
||||
|
||||
return( rv);
|
||||
}
|
||||
}
|
||||
|
||||
inFile->Release();
|
||||
|
||||
if (NS_SUCCEEDED( rv)) {
|
||||
ReportSuccess( name, msgCount, &success);
|
||||
}
|
||||
else {
|
||||
ReportError( OEIMPORT_MAILBOX_CONVERTERROR, name, &error);
|
||||
}
|
||||
|
||||
SetLogs( success, error, pErrorLog, pSuccessLog);
|
||||
|
||||
return( rv);
|
||||
}
|
||||
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче