nsresult nsEudoraCompose::ReadHeaders( ReadFileState *pState, SimpleBufferTonyRCopiedOnce& copy, SimpleBufferTonyRCopiedOnce& header) { // This should be the headers... header.m_writeOffset = 0; nsresult rv; PRInt32 lineLen; PRInt32 endLen = -1; PRInt8 endBuffer = 0; while ((endLen = IsEndHeaders( copy)) == -1) { while ((lineLen = FindNextEndLine( copy)) == -1) { copy.m_writeOffset = copy.m_bytesInBuf; if (!header.Write( copy.m_pBuffer, copy.m_writeOffset)) { IMPORT_LOG0( "*** ERROR, writing headers\n"); return( NS_ERROR_FAILURE); } if (NS_FAILED( rv = FillMailBuffer( pState, copy))) { IMPORT_LOG0( "*** Error reading message headers\n"); return( rv); } if (!copy.m_bytesInBuf) { IMPORT_LOG0( "*** Error, end of file while reading headers\n"); return( NS_ERROR_FAILURE); } } copy.m_writeOffset += lineLen; if ((copy.m_writeOffset + 4) >= copy.m_bytesInBuf) { if (!header.Write( copy.m_pBuffer, copy.m_writeOffset)) { IMPORT_LOG0( "*** ERROR, writing headers 2\n"); return( NS_ERROR_FAILURE); } if (NS_FAILED( rv = FillMailBuffer( pState, copy))) { IMPORT_LOG0( "*** Error reading message headers 2\n"); return( rv); } } } if (!header.Write( copy.m_pBuffer, copy.m_writeOffset)) { IMPORT_LOG0( "*** Error writing final headers\n"); return( NS_ERROR_FAILURE); } if (!header.Write( (const char *)&endBuffer, 1)) { IMPORT_LOG0( "*** Error writing header trailing null\n"); return( NS_ERROR_FAILURE); } copy.m_writeOffset += endLen; return( NS_OK); }
PRBool nsEudoraWin32::ImportSettings( nsIFile *pIniFile, nsIMsgAccount **localMailAccount) { PRBool result = PR_FALSE; nsresult rv; nsCOMPtr<nsIMsgAccountManager> accMgr = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv); if (NS_FAILED(rv)) { IMPORT_LOG0( "*** Failed to create a account manager!\n"); return( PR_FALSE); } // Eudora info is arranged by key, 1 for the default, then persona's for additional // accounts. // Start with the first one, then do each persona nsCString iniPath; pIniFile->GetNativePath(iniPath); if (iniPath.IsEmpty()) return( PR_FALSE); UINT valInt; SimpleBufferTonyRCopiedOnce section; DWORD sSize; DWORD sOffset = 0; DWORD start; nsCString sectionName("Settings"); int popCount = 0; int accounts = 0; DWORD allocSize = 0; do { allocSize += 2048; section.Allocate( allocSize); sSize = ::GetPrivateProfileSection( "Personalities", section.m_pBuffer, allocSize, iniPath.get()); } while (sSize == (allocSize - 2)); nsIMsgAccount * pAccount; do { if (!sectionName.IsEmpty()) { pAccount = nsnull; valInt = ::GetPrivateProfileInt( sectionName.get(), "UsesPOP", 1, iniPath.get()); if (valInt) { // This is a POP account if (BuildPOPAccount( accMgr, sectionName.get(), iniPath.get(), &pAccount)) { accounts++; popCount++; if (popCount > 1) { if (localMailAccount && *localMailAccount) { NS_RELEASE( *localMailAccount); *localMailAccount = nsnull; } } else { if (localMailAccount) { *localMailAccount = pAccount; NS_IF_ADDREF( pAccount); } } } } else { valInt = ::GetPrivateProfileInt( sectionName.get(), "UsesIMAP", 0, iniPath.get()); if (valInt) { // This is an IMAP account if (BuildIMAPAccount( accMgr, sectionName.get(), iniPath.get(), &pAccount)) accounts++; } } if (pAccount && (sOffset == 0)) accMgr->SetDefaultAccount( pAccount); NS_IF_RELEASE( pAccount); } sectionName.Truncate(); while ((sOffset < sSize) && (section.m_pBuffer[sOffset] != '=')) sOffset++; sOffset++; start = sOffset; while ((sOffset < sSize) && (section.m_pBuffer[sOffset] != 0)) sOffset++; if (sOffset > start) { sectionName.Append( section.m_pBuffer + start, sOffset - start); sectionName.Trim( kWhitespace); } } while (sOffset < sSize); // 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 nsEudoraMailbox::ReadNextMessage(ReadFileState *pState, SimpleBufferTonyRCopiedOnce& copy, SimpleBufferTonyRCopiedOnce& header, SimpleBufferTonyRCopiedOnce& body, nsCString& defaultDate, nsCString& bodyType, EudoraTOCEntry *pTocEntry) { header.m_writeOffset = 0; body.m_writeOffset = 0; nsresult rv; int32_t lineLen; char endBuffer = 0; lineLen = -1; // Find the from separator - we should actually be positioned at the // from separator, but for now, we'll verify this. while (lineLen == -1) { if (NS_FAILED(rv = FillMailBuffer(pState, copy))) { IMPORT_LOG0("*** Error, FillMailBuffer FAILED in ReadNextMessage\n"); return rv; } lineLen = IsEudoraFromSeparator(copy.m_pBuffer + copy.m_writeOffset, copy.m_bytesInBuf - copy.m_writeOffset, defaultDate); if (lineLen == -1) { while ((lineLen = FindStartLine(copy)) == -1) { copy.m_writeOffset = copy.m_bytesInBuf; if (NS_FAILED(rv = FillMailBuffer(pState, copy))) { IMPORT_LOG0("*** Error, FillMailBuffer FAILED in ReadNextMessage, looking for next start line\n"); return rv; } if (!copy.m_bytesInBuf) { IMPORT_LOG0("*** Error, ReadNextMessage, looking for start of next line, got end of file.\n"); return NS_ERROR_FAILURE; } } copy.m_writeOffset += lineLen; lineLen = -1; } } // Skip past the from line separator while ((lineLen = FindStartLine(copy)) == -1) { copy.m_writeOffset = copy.m_bytesInBuf; if (NS_FAILED(rv = FillMailBuffer(pState, copy))) { IMPORT_LOG0("*** Error, ReadNextMessage, FillMailBuffer failed looking for from sep\n"); return rv; } if (!copy.m_bytesInBuf) { IMPORT_LOG0("*** Error, ReadNextMessage, end of file looking for from sep\n"); return NS_ERROR_FAILURE; } } copy.m_writeOffset += lineLen; if (NS_FAILED(rv = FillMailBuffer(pState, copy))) { IMPORT_LOG0("*** Error, Unable to fill mail buffer after from sep.\n"); return rv; } // This should be the headers... int32_t endLen = -1; while ((endLen = IsEndHeaders(copy)) == -1) { while ((lineLen = FindNextEndLine(copy)) == -1) { copy.m_writeOffset = copy.m_bytesInBuf; if (!header.Write(copy.m_pBuffer, copy.m_writeOffset)) { IMPORT_LOG0("*** ERROR, writing headers\n"); return NS_ERROR_FAILURE; } if (NS_FAILED(rv = FillMailBuffer(pState, copy))) { IMPORT_LOG0("*** Error reading message headers\n"); return rv; } if (!copy.m_bytesInBuf) { IMPORT_LOG0("*** Error, end of file while reading headers\n"); return NS_ERROR_FAILURE; } } copy.m_writeOffset += lineLen; if ((copy.m_writeOffset + 4) >= copy.m_bytesInBuf) { if (!header.Write(copy.m_pBuffer, copy.m_writeOffset)) { IMPORT_LOG0("*** ERROR, writing headers 2\n"); return NS_ERROR_FAILURE; } if (NS_FAILED(rv = FillMailBuffer(pState, copy))) { IMPORT_LOG0("*** Error reading message headers 2\n"); return rv; } } } if (!header.Write(copy.m_pBuffer, copy.m_writeOffset)) { IMPORT_LOG0("*** Error writing final headers\n"); return NS_ERROR_FAILURE; } if (pTocEntry) { // This is not the prettiest spot to stick this code, but it works and it was convenient. char header_str[128]; // Write X-Mozilla-Status header PR_snprintf(header_str, 128, MSG_LINEBREAK X_MOZILLA_STATUS_FORMAT MSG_LINEBREAK, pTocEntry->GetMozillaStatusFlags()); header.Write(header_str, strlen(header_str)); // Write X-Mozilla-Status2 header PR_snprintf(header_str, 128, X_MOZILLA_STATUS2_FORMAT MSG_LINEBREAK, pTocEntry->GetMozillaStatus2Flags()); header.Write(header_str, strlen(header_str)); // Format and write X-Mozilla-Keys header nsCString keywordHdr(X_MOZILLA_KEYWORDS); if (pTocEntry->HasEudoraLabel()) { PR_snprintf(header_str, 128, "eudoralabel%d", pTocEntry->GetLabelNumber()); keywordHdr.Replace(sizeof(HEADER_X_MOZILLA_KEYWORDS) + 1, strlen(header_str), header_str); } header.Write(keywordHdr.get(), keywordHdr.Length()); } if (!header.Write(&endBuffer, 1)) { IMPORT_LOG0("*** Error writing header trailing null\n"); return NS_ERROR_FAILURE; } copy.m_writeOffset += endLen; if (NS_FAILED(rv = FillMailBuffer(pState, copy))) { IMPORT_LOG0("*** Error reading beginning of message body\n"); return rv; } EmptyAttachments(); // Get the body! // Read one line at a time here and look for the next separator nsCString tmp; bool insideEudoraTags = false; // by default we consider the body text to be plain text bodyType = "text/plain"; while ((lineLen = IsEudoraFromSeparator(copy.m_pBuffer + copy.m_writeOffset, copy.m_bytesInBuf - copy.m_writeOffset, tmp)) == -1) { int32_t tagLength = 0; if (IsEudoraTag (copy.m_pBuffer + copy.m_writeOffset, copy.m_bytesInBuf - copy.m_writeOffset, insideEudoraTags, bodyType, tagLength)) { // We don't want to keep eudora tags so skip over them. // let's write the previous text if (!body.Write(copy.m_pBuffer, copy.m_writeOffset)) { IMPORT_LOG0("*** Error writing to message body\n"); return NS_ERROR_FAILURE; } // we want to skip over the tag...for now we are assuming the tag is always at the start of line. copy.m_writeOffset += tagLength; if (NS_FAILED(rv = FillMailBuffer(pState, copy))) { IMPORT_LOG0("*** Error reading message body\n"); return rv; } if (!copy.m_bytesInBuf) break; continue; } // Eudora Attachment lines are always outside Eudora Tags // so we shouldn't try to find one here if (!insideEudoraTags) { // Debatable is whether or not to exclude these lines from the // text of the message, I prefer not to in case the original // attachment is actually missing. rv = ExamineAttachment(copy); if (NS_FAILED(rv)) { IMPORT_LOG0("*** Error examining attachment line\n"); return rv; } } while (((lineLen = FindStartLine(copy)) == -1) && copy.m_bytesInBuf) { copy.m_writeOffset = copy.m_bytesInBuf; if (!body.Write(copy.m_pBuffer, copy.m_writeOffset)) { IMPORT_LOG0("*** Error writing to message body\n"); return NS_ERROR_FAILURE; } if (NS_FAILED(rv = FillMailBuffer(pState, copy))) { IMPORT_LOG0("*** Error reading message body\n"); return rv; } } if (!copy.m_bytesInBuf) break; copy.m_writeOffset += lineLen; // found the start of the next line // make sure it's long enough to check for the from line if ((copy.m_writeOffset + 2048) >= copy.m_bytesInBuf) { if (!body.Write(copy.m_pBuffer, copy.m_writeOffset)) { IMPORT_LOG0("*** Error writing to message body 2\n"); return NS_ERROR_FAILURE; } if (NS_FAILED(rv = FillMailBuffer(pState, copy))) { IMPORT_LOG0("*** Error reading message body 2\n"); return rv; } } } // the start of the current line is a from, we-re done if (!body.Write(copy.m_pBuffer, copy.m_writeOffset)) { IMPORT_LOG0("*** Error writing final message body\n"); return NS_ERROR_FAILURE; } if (!body.Write(&endBuffer, 1)) { IMPORT_LOG0("*** Error writing body trailing null\n"); IMPORT_LOG2("\tbody.m_size: %ld, body.m_writeOffset: %ld\n", body.m_size, body.m_writeOffset); return NS_ERROR_FAILURE; } if (NS_FAILED(rv = FillMailBuffer(pState, copy))) { IMPORT_LOG0("*** Error filling mail buffer for next read message\n"); return rv; } return NS_OK; }
nsresult nsEudoraMailbox::ImportMessage( SimpleBufferTonyRCopiedOnce &headers, SimpleBufferTonyRCopiedOnce &body, nsCString& defaultDate, nsAutoCString& bodyType, nsIOutputStream *pDst, int32_t *pMsgCount) { nsresult rv = NS_OK; uint32_t written = 0; nsEudoraCompose compose; // Unfortunately Eudora stores HTML messages in the sent folder // without any content type header at all. If the first line of the message body is <html> // then mark the message as html internally...See Bug #258489 if (body.m_pBuffer && (body.m_writeOffset > (int32_t)strlen(kHTMLTag)) && (strncmp(body.m_pBuffer, kHTMLTag, strlen(kHTMLTag)) == 0)) bodyType = "text/html"; // ignore whatever body type we were given...force html compose.SetBody(body.m_pBuffer, body.m_writeOffset - 1, bodyType); compose.SetHeaders(headers.m_pBuffer, headers.m_writeOffset - 1); compose.SetAttachments(&m_attachments); compose.SetDefaultDate(defaultDate); nsCOMPtr <nsIFile> compositionFile; rv = compose.SendTheMessage(m_mailImportLocation, getter_AddRefs(compositionFile)); if (NS_SUCCEEDED(rv)) { nsCString fromLine(eudoraFromLine); SimpleBufferTonyRCopiedOnce copy; copy.Allocate(kCopyBufferSize); /* IMPORT_LOG0("Composed message in file: "); DUMP_FILENAME(compositionFile, true); */ // copy the resulting file into the destination file! rv = compose.CopyComposedMessage(fromLine, compositionFile, pDst, copy); DeleteFile(compositionFile); if (NS_FAILED(rv)) IMPORT_LOG0("*** Error copying composed message to destination mailbox\n"); if (pMsgCount) (*pMsgCount)++; } else { IMPORT_LOG0("*** Error composing message, writing raw message\n"); rv = WriteFromSep(pDst); rv = pDst->Write(kComposeErrorStr, strlen(kComposeErrorStr), &written); if (NS_SUCCEEDED(rv)) rv = pDst->Write(headers.m_pBuffer, headers.m_writeOffset - 1, &written); if (NS_SUCCEEDED(rv) && (written == (headers.m_writeOffset - 1))) rv = pDst->Write("\x0D\x0A" "\x0D\x0A", 4, &written); if (NS_SUCCEEDED(rv) && (written == 4)) rv = pDst->Write(body.m_pBuffer, body.m_writeOffset - 1, &written); if (NS_SUCCEEDED(rv) && (written == (body.m_writeOffset - 1))) { rv = pDst->Write("\x0D\x0A", 2, &written); if (written != 2) rv = NS_ERROR_FAILURE; } if (NS_FAILED(rv)) IMPORT_LOG0("*** Error writing to destination mailbox\n"); } return rv; }
nsresult nsEudoraMailbox::ImportMailboxUsingTOC( uint32_t *pBytes, bool *pAbort, nsIInputStream *pInputStream, nsIFile *tocFile, nsIMsgFolder *dstFolder, int32_t *pMsgCount) { nsresult rv = NS_OK; int64_t mailSize = m_mailSize; int64_t tocSize = 0; uint32_t saveBytes = pBytes ? *pBytes : 0; nsCOMPtr <nsIInputStream> tocInputStream; rv = tocFile->GetFileSize(&tocSize); // if the index or the mail file is empty then just // use the original mail file. if (!mailSize || !tocSize) return NS_ERROR_FAILURE; rv = NS_NewLocalFileInputStream(getter_AddRefs(tocInputStream), tocFile); NS_ENSURE_SUCCESS(rv, rv); SimpleBufferTonyRCopiedOnce readBuffer; SimpleBufferTonyRCopiedOnce headers; SimpleBufferTonyRCopiedOnce body; SimpleBufferTonyRCopiedOnce copy; int32_t tocOffset = kMsgFirstOffset; EudoraTOCEntry tocEntry; copy.Allocate(kCopyBufferSize); readBuffer.Allocate(kMailReadBufferSize); IMPORT_LOG0("Importing mailbox using TOC: "); DUMP_FILENAME(tocFile, true); nsCOMPtr<nsISeekableStream> tocSeekableStream = do_QueryInterface(tocInputStream); nsCOMPtr<nsISeekableStream> mailboxSeekableStream = do_QueryInterface(pInputStream); nsCOMPtr<nsIOutputStream> outputStream; nsCOMPtr<nsIMsgPluggableStore> msgStore; rv = dstFolder->GetMsgStore(getter_AddRefs(msgStore)); NS_ENSURE_SUCCESS(rv, rv); while (!*pAbort && (tocOffset < (int32_t)tocSize)) { if (NS_FAILED(rv = tocSeekableStream->Seek(nsISeekableStream::NS_SEEK_SET, tocOffset))) break; if (NS_FAILED(rv = ReadTOCEntry(tocInputStream, tocEntry))) break; nsCOMPtr<nsIMsgDBHdr> msgHdr; bool reusable; rv = msgStore->GetNewMsgOutputStream(dstFolder, getter_AddRefs(msgHdr), &reusable, getter_AddRefs(outputStream)); if (NS_FAILED(rv)) break; // Quick and dirty way to read in and parse the message the way the rest // of the code expects. nsCString defaultDate; nsAutoCString bodyType; ReadFileState state; // Seek to the start of the email message. mailboxSeekableStream->Seek(nsISeekableStream::NS_SEEK_SET, tocEntry.m_Offset); // We're fudging the data to make ReadNextMessage happy. In particular // state.size is meant to be the size of the entire file, because it's // assumed that ReadNextMessage will actually have to parse. We know // exactly how big the message is, so we simply set the "size" to be // immediately where the message ends. state.offset = tocEntry.m_Offset; state.pInputStream = pInputStream; state.size = state.offset + tocEntry.m_Length; if (NS_SUCCEEDED(rv = ReadNextMessage(&state, readBuffer, headers, body, defaultDate, bodyType, &tocEntry))) { rv = ImportMessage(headers, body, defaultDate, bodyType, outputStream, pMsgCount); if (pBytes) *pBytes += tocEntry.m_Length; if (NS_SUCCEEDED(rv)) msgStore->FinishNewMessage(outputStream, msgHdr); else { msgStore->DiscardNewMessage(outputStream, msgHdr); IMPORT_LOG0( "*** Error importing message\n"); } } // We currently don't consider an error from ReadNextMessage or ImportMessage to be fatal. // Reset the error back to no error in case this is the last time through the loop. rv = NS_OK; tocOffset += kMsgHeaderSize; if (!reusable) outputStream->Close(); } if (outputStream) outputStream->Close(); if (NS_SUCCEEDED(rv)) { IMPORT_LOG0(" finished\n"); } else { // We failed somewhere important enough that we kept the error. // Bail on all that we imported since we'll be importing everything // again using just the mailbox. IMPORT_LOG0("*** Error importing mailbox using TOC: "); // DUMP_FILENAME(pMail, true); // Reset pBytes back to where it was before we imported this mailbox. // This will likely result in a funky progress bar which will move // backwards, but that's probably the best we can do to keep the // progress accurate since we'll be re-importing the same mailbox. if (pBytes) *pBytes = saveBytes; // Set the message count back to 0. if (pMsgCount) *pMsgCount = 0; } return rv; }
nsresult nsEudoraMailbox::ImportMailbox(uint32_t *pBytes, bool *pAbort, const PRUnichar *pName, nsIFile *pSrc, nsIMsgFolder *dstFolder, int32_t *pMsgCount) { nsCOMPtr<nsIFile> tocFile; nsCOMPtr<nsIInputStream> srcInputStream; nsCOMPtr<nsIInputStream> tocInputStream; nsCOMPtr<nsIOutputStream> mailOutputStream; bool importWithoutToc = true; bool deleteToc = false; nsCOMPtr<nsIFile> mailFile; if (pMsgCount) *pMsgCount = 0; nsresult rv = pSrc->GetFileSize(&m_mailSize); rv = NS_NewLocalFileInputStream(getter_AddRefs(srcInputStream), pSrc); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIFile> srcFile(pSrc); // First, get the index file for this mailbox rv = FindTOCFile(pSrc, getter_AddRefs(tocFile), &deleteToc); if (NS_SUCCEEDED(rv) && tocFile) { IMPORT_LOG0("Reading euroda toc file: "); DUMP_FILENAME(tocFile, true); // Read the toc and import the messages rv = ImportMailboxUsingTOC(pBytes, pAbort, srcInputStream, tocFile, dstFolder, pMsgCount); // clean up if (deleteToc) DeleteFile(tocFile); // If we were able to import with the TOC, then we don't need to bother // importing without the TOC. if (NS_SUCCEEDED(rv)) { importWithoutToc = false; IMPORT_LOG0("Imported mailbox: "); DUMP_FILENAME(pSrc, false); IMPORT_LOG0(" Using TOC: "); DUMP_FILENAME(tocFile, true); } else { IMPORT_LOG0("*** Error importing with TOC - will import without TOC.\n"); } } // pSrc must be Released before returning if (importWithoutToc) { // The source file contains partially constructed mail messages, // and attachments. We should first investigate if we can use the mailnews msgCompose // stuff to do the work for us. If not we have to scan the mailboxes and do TONS // of work to properly reconstruct the message - Eudora is so nice that it strips things // like MIME headers, character encoding, and attachments - beautiful! rv = pSrc->GetFileSize(&m_mailSize); SimpleBufferTonyRCopiedOnce readBuffer; SimpleBufferTonyRCopiedOnce headers; SimpleBufferTonyRCopiedOnce body; SimpleBufferTonyRCopiedOnce copy; headers.m_convertCRs = true; body.m_convertCRs = true; copy.Allocate(kCopyBufferSize); readBuffer.Allocate(kMailReadBufferSize); ReadFileState state; state.offset = 0; state.size = m_mailSize; state.pFile = pSrc; IMPORT_LOG0("Reading mailbox\n"); if (NS_SUCCEEDED(rv)) { nsCString defaultDate; nsAutoCString bodyType; IMPORT_LOG0("Reading first message\n"); nsCOMPtr<nsIOutputStream> outputStream; nsCOMPtr<nsIMsgPluggableStore> msgStore; rv = dstFolder->GetMsgStore(getter_AddRefs(msgStore)); NS_ENSURE_SUCCESS(rv, rv); while (!*pAbort && NS_SUCCEEDED(rv = ReadNextMessage( &state, readBuffer, headers, body, defaultDate, bodyType, NULL))) { if (pBytes) *pBytes += body.m_writeOffset - 1 + headers.m_writeOffset - 1; nsCOMPtr<nsIMsgDBHdr> msgHdr; bool reusable; rv = msgStore->GetNewMsgOutputStream(dstFolder, getter_AddRefs(msgHdr), &reusable, getter_AddRefs(outputStream)); if (NS_FAILED(rv)) break; rv = ImportMessage(headers, body, defaultDate, bodyType, outputStream, pMsgCount); if (NS_SUCCEEDED(rv)) msgStore->FinishNewMessage(outputStream, msgHdr); else { msgStore->DiscardNewMessage(outputStream, msgHdr); IMPORT_LOG0( "*** Error importing message\n"); } if (!reusable) outputStream->Close(); if (!readBuffer.m_bytesInBuf && (state.offset >= state.size)) break; } if (outputStream) outputStream->Close(); } else { IMPORT_LOG0("*** Error creating file spec for composition\n"); } } return rv; }
nsresult nsEudoraMailbox::ImportMailboxUsingTOC( PRUint32 *pBytes, PRBool *pAbort, nsIInputStream *pInputStream, nsIFile *tocFile, nsIOutputStream *pDst, PRInt32 *pMsgCount) { nsresult rv = NS_OK; PRInt64 mailSize = m_mailSize; PRInt64 tocSize = 0; PRUint32 saveBytes = pBytes ? *pBytes : 0; nsCOMPtr <nsIInputStream> tocInputStream; rv = tocFile->GetFileSize( &tocSize); // if the index or the mail file is empty then just // use the original mail file. if (!mailSize || !tocSize) return NS_ERROR_FAILURE; rv = NS_NewLocalFileInputStream(getter_AddRefs(tocInputStream), tocFile); NS_ENSURE_SUCCESS(rv, rv); SimpleBufferTonyRCopiedOnce readBuffer; SimpleBufferTonyRCopiedOnce headers; SimpleBufferTonyRCopiedOnce body; SimpleBufferTonyRCopiedOnce copy; PRInt32 tocOffset = kMsgFirstOffset; EudoraTOCEntry tocEntry; copy.Allocate( kCopyBufferSize); readBuffer.Allocate(kMailReadBufferSize); IMPORT_LOG0( "Importing mailbox using TOC: "); DUMP_FILENAME( tocFile, PR_TRUE); nsCOMPtr <nsISeekableStream> tocSeekableStream = do_QueryInterface(tocInputStream); nsCOMPtr <nsISeekableStream> mailboxSeekableStream = do_QueryInterface(pInputStream); while (!*pAbort && (tocOffset < (PRInt32)tocSize)) { if ( NS_FAILED(rv = tocSeekableStream->Seek(nsISeekableStream::NS_SEEK_SET, tocOffset)) ) break; if ( NS_FAILED(rv = ReadTOCEntry(tocInputStream, tocEntry)) ) break; // Quick and dirty way to read in and parse the message the way the rest // of the code expects. nsCString defaultDate; nsCAutoString bodyType; ReadFileState state; // Seek to the start of the email message. mailboxSeekableStream->Seek(nsISeekableStream::NS_SEEK_SET, tocEntry.m_Offset); // We're fudging the data to make ReadNextMessage happy. In particular // state.size is meant to be the size of the entire file, because it's // assumed that ReadNextMessage will actually have to parse. We know // exactly how big the message is, so we simply set the "size" to be // immediately where the message ends. state.offset = tocEntry.m_Offset; state.pInputStream = pInputStream; state.size = state.offset + tocEntry.m_Length; if ( NS_SUCCEEDED(rv = ReadNextMessage(&state, readBuffer, headers, body, defaultDate, bodyType, &tocEntry) ) ) { rv = ImportMessage(headers, body, defaultDate, bodyType, pDst, pMsgCount); if (pBytes) *pBytes += tocEntry.m_Length; } // We currently don't consider an error from ReadNextMessage or ImportMessage to be fatal. // Reset the error back to no error in case this is the last time through the loop. rv = NS_OK; tocOffset += kMsgHeaderSize; } if ( NS_SUCCEEDED(rv) ) { IMPORT_LOG0( " finished\n"); } else { // We failed somewhere important enough that we kept the error. // Bail on all that we imported since we'll be importing everything // again using just the mailbox. IMPORT_LOG0( "*** Error importing mailbox using TOC: "); // DUMP_FILENAME(pMail, PR_TRUE); // Close the destination and truncate it. We don't need to bother // to reopen it because the nsIFileSpec implementation will open // before writing if necessary (and yes legacy importing code already // relies on this behavior). // pDst->CloseStream(); // pDst->Truncate(0); // Reset pBytes back to where it was before we imported this mailbox. // This will likely result in a funky progress bar which will move // backwards, but that's probably the best we can do to keep the // progress accurate since we'll be re-importing the same mailbox. if (pBytes) *pBytes = saveBytes; // Set the message count back to 0. if (pMsgCount) *pMsgCount = 0; } return rv; }