mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-04 21:18:35 +00:00
add hidden pref to write downloaded pop3 mail to temp file first, to let virus checkers have a shot before they delete the whole mail folder, sr=mscott 116443
This commit is contained in:
parent
1e70ab26d7
commit
7d0d2ee0bc
@ -226,3 +226,6 @@
|
||||
## @loc None
|
||||
4037=Unable to locate mail spool file.
|
||||
|
||||
## @name POP3_TMP_DOWNLOAD_FAILED
|
||||
## @loc None
|
||||
4038=There was an error downloading the following message: \nFrom: %S\n Subject: %S\n This message may contain a virus or there is not enough disk space. Skip this message?
|
||||
|
@ -154,6 +154,8 @@ NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_MAILNEWS, value)
|
||||
|
||||
#define NS_MSG_USER_NOT_AUTHENTICATED NS_MSG_GENERATE_FAILURE(30) // when local caches are password protect and user isn't auth
|
||||
|
||||
#define NS_MSG_ERROR_COPYING_FROM_TMP_DOWNLOAD NS_MSG_GENERATE_FAILURE(31) // pop3 downloaded to tmp file, and failed.
|
||||
|
||||
#define NS_MSGCOMP_ERROR_BEGIN 12500
|
||||
/* NS_ERROR_NNTP_NO_CROSS_POSTING lives here, and not in nsMsgComposeStringBundle.h, because it is used in news and compose. */
|
||||
#define NS_ERROR_NNTP_NO_CROSS_POSTING NS_MSG_GENERATE_FAILURE(12554)
|
||||
|
@ -242,3 +242,7 @@
|
||||
## @loc None
|
||||
4037=Unable to locate mail spool file.
|
||||
|
||||
## @name POP3_TMP_DOWNLOAD_FAILED
|
||||
## @loc None
|
||||
4038=There was an error downloading the following message: \nFrom: %S\n Subject: %S\n This message may contain a virus or there is not enough disk space. Skip this message?
|
||||
|
||||
|
@ -58,12 +58,14 @@ REQUIRES = xpcom \
|
||||
intl \
|
||||
unicharutil \
|
||||
mime \
|
||||
dom \
|
||||
rdfutil \
|
||||
txmgr \
|
||||
caps \
|
||||
docshell \
|
||||
msgimap \
|
||||
nkcache \
|
||||
windowwatcher \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
|
@ -1906,7 +1906,7 @@ nsMsgLocalMailFolder::CopyFolderLocal(nsIMsgFolder *srcFolder, PRBool isMoveFold
|
||||
{
|
||||
// do it just for the parent folder (isMoveFolder is true for parent only) if we are deleting/moving a folder tree
|
||||
// don't confirm for rss folders.
|
||||
if (isMoveFolder && strcmp(GetIncomingServerType(), "rss"))
|
||||
if (isMoveFolder)
|
||||
{
|
||||
PRBool okToDelete = PR_FALSE;
|
||||
ConfirmFolderDeletion(msgWindow, &okToDelete);
|
||||
|
@ -94,5 +94,6 @@ private:
|
||||
#define MOVEMAIL_CANT_DELETE_LOCK 4035
|
||||
#define MOVEMAIL_CANT_TRUNCATE_SPOOL_FILE 4036
|
||||
#define MOVEMAIL_SPOOL_FILE_NOT_FOUND 4037
|
||||
#define POP3_TMP_DOWNLOAD_FAILED 4038
|
||||
|
||||
#endif /* _nsLocalStringBundle_H__ */
|
||||
|
@ -345,19 +345,12 @@ void nsMsgMailboxParser::UpdateDBFolderInfo(nsIMsgDatabase *mailDB)
|
||||
mailDB->Commit(nsMsgDBCommitType::kLargeCommit);
|
||||
}
|
||||
|
||||
// By default, do nothing
|
||||
void nsMsgMailboxParser::FolderTypeSpecificTweakMsgHeader(nsIMsgDBHdr * /* tweakMe */)
|
||||
{
|
||||
}
|
||||
|
||||
// Tell the world about the message header (add to db, and view, if any)
|
||||
PRInt32 nsMsgMailboxParser::PublishMsgHeader(nsIMsgWindow *msgWindow)
|
||||
{
|
||||
FinishHeader();
|
||||
if (m_newMsgHdr)
|
||||
{
|
||||
FolderTypeSpecificTweakMsgHeader(m_newMsgHdr);
|
||||
|
||||
PRUint32 flags;
|
||||
(void)m_newMsgHdr->GetFlags(&flags);
|
||||
if (flags & MSG_FLAG_EXPUNGED)
|
||||
@ -1478,7 +1471,7 @@ nsParseNewMailState::Init(nsIMsgFolder *serverFolder, nsIMsgFolder *downloadFold
|
||||
if (m_filterList)
|
||||
{
|
||||
rv = server->ConfigureTemporaryFilters(m_filterList);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to configure temp filters");
|
||||
// NS_ASSERTION(NS_SUCCEEDED(rv), "failed to configure temp filters");
|
||||
}
|
||||
}
|
||||
m_disableFilters = PR_FALSE;
|
||||
@ -1532,12 +1525,13 @@ PRInt32 nsParseNewMailState::PublishMsgHeader(nsIMsgWindow *msgWindow)
|
||||
|
||||
if (m_newMsgHdr)
|
||||
{
|
||||
FolderTypeSpecificTweakMsgHeader(m_newMsgHdr);
|
||||
if (!m_disableFilters)
|
||||
{
|
||||
// flush the inbox because filters will read from disk
|
||||
m_inboxFileStream->flush();
|
||||
ApplyFilters(&moved, msgWindow);
|
||||
PRUint32 msgOffset;
|
||||
(void) m_newMsgHdr->GetMessageOffset(&msgOffset);
|
||||
ApplyFilters(&moved, msgWindow, msgOffset);
|
||||
}
|
||||
if (!moved)
|
||||
{
|
||||
@ -1579,28 +1573,31 @@ nsresult nsParseNewMailState::GetTrashFolder(nsIMsgFolder **pTrashFolder)
|
||||
return rv;
|
||||
}
|
||||
|
||||
void nsParseNewMailState::ApplyFilters(PRBool *pMoved, nsIMsgWindow *msgWindow)
|
||||
void nsParseNewMailState::ApplyFilters(PRBool *pMoved, nsIMsgWindow *msgWindow, PRUint32 msgOffset)
|
||||
{
|
||||
m_msgMovedByFilter = PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIMsgDBHdr> msgHdr = m_newMsgHdr;
|
||||
nsCOMPtr<nsIMsgFolder> downloadFolder = m_downloadFolder;
|
||||
nsCOMPtr <nsIMsgFolder> rootMsgFolder = do_QueryInterface(m_rootFolder);
|
||||
if (rootMsgFolder)
|
||||
m_curHdrOffset = msgOffset;
|
||||
|
||||
if (!m_disableFilters)
|
||||
{
|
||||
PRUint32 numFolders;
|
||||
if (!downloadFolder)
|
||||
rootMsgFolder->GetFoldersWithFlag(MSG_FOLDER_FLAG_INBOX, 1, &numFolders, getter_AddRefs(downloadFolder));
|
||||
if (downloadFolder)
|
||||
downloadFolder->GetURI(getter_Copies(m_inboxUri));
|
||||
char * headers = m_headers.GetBuffer();
|
||||
PRUint32 headersSize = m_headers.GetBufferPos();
|
||||
nsresult matchTermStatus;
|
||||
if (m_filterList)
|
||||
matchTermStatus = m_filterList->ApplyFiltersToHdr(nsMsgFilterType::InboxRule,
|
||||
msgHdr, downloadFolder, m_mailDB, headers, headersSize, this, msgWindow);
|
||||
nsCOMPtr<nsIMsgDBHdr> msgHdr = m_newMsgHdr;
|
||||
nsCOMPtr<nsIMsgFolder> downloadFolder = m_downloadFolder;
|
||||
nsCOMPtr <nsIMsgFolder> rootMsgFolder = do_QueryInterface(m_rootFolder);
|
||||
if (rootMsgFolder)
|
||||
{
|
||||
PRUint32 numFolders;
|
||||
if (!downloadFolder)
|
||||
rootMsgFolder->GetFoldersWithFlag(MSG_FOLDER_FLAG_INBOX, 1, &numFolders, getter_AddRefs(downloadFolder));
|
||||
if (downloadFolder)
|
||||
downloadFolder->GetURI(getter_Copies(m_inboxUri));
|
||||
char * headers = m_headers.GetBuffer();
|
||||
PRUint32 headersSize = m_headers.GetBufferPos();
|
||||
nsresult matchTermStatus;
|
||||
if (m_filterList)
|
||||
matchTermStatus = m_filterList->ApplyFiltersToHdr(nsMsgFilterType::InboxRule,
|
||||
msgHdr, downloadFolder, m_mailDB, headers, headersSize, this, msgWindow);
|
||||
}
|
||||
}
|
||||
|
||||
if (pMoved)
|
||||
*pMoved = m_msgMovedByFilter;
|
||||
}
|
||||
@ -1696,9 +1693,9 @@ NS_IMETHODIMP nsParseNewMailState::ApplyFilterHit(nsIMsgFilter *filter, nsIMsgWi
|
||||
else
|
||||
{
|
||||
err = MoveIncorporatedMessage(msgHdr, m_mailDB, destIFolder, filter, msgWindow);
|
||||
m_msgMovedByFilter = PR_TRUE;
|
||||
// cleanup after mailHdr in source DB because we moved the message.
|
||||
m_mailDB->RemoveHeaderMdbRow(msgHdr);
|
||||
m_msgMovedByFilter = PR_TRUE;
|
||||
}
|
||||
if (NS_SUCCEEDED(err))
|
||||
{
|
||||
@ -1853,6 +1850,62 @@ nsresult nsParseNewMailState::EndMsgDownload()
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsParseNewMailState::AppendMsgFromFile(nsIOFileStream *fileStream,
|
||||
PRInt32 offset, PRUint32 length,
|
||||
nsFileSpec &destFileSpec)
|
||||
{
|
||||
fileStream->seek(PR_SEEK_SET, offset);
|
||||
|
||||
nsIOFileStream *destFile = new nsIOFileStream(destFileSpec, PR_WRONLY | PR_CREATE_FILE);
|
||||
|
||||
if (!destFile)
|
||||
{
|
||||
#ifdef DEBUG_bienvenu
|
||||
NS_ASSERTION(PR_FALSE, "out of memory");
|
||||
#endif
|
||||
return NS_MSG_ERROR_WRITING_MAIL_FOLDER;
|
||||
}
|
||||
|
||||
destFile->seek(PR_SEEK_END, 0);
|
||||
PRInt32 newMsgPos = destFile->tell();
|
||||
|
||||
if (!m_ibuffer)
|
||||
m_ibuffer_size = 10240;
|
||||
m_ibuffer_fp = 0;
|
||||
|
||||
while (!m_ibuffer && (m_ibuffer_size >= 512))
|
||||
{
|
||||
m_ibuffer = (char *) PR_Malloc(m_ibuffer_size);
|
||||
if (m_ibuffer == nsnull)
|
||||
m_ibuffer_size /= 2;
|
||||
}
|
||||
NS_ASSERTION(m_ibuffer != nsnull, "couldn't get memory to move msg");
|
||||
while ((length > 0) && m_ibuffer)
|
||||
{
|
||||
PRUint32 nRead = m_inboxFileStream->read (m_ibuffer, length > m_ibuffer_size ? m_ibuffer_size : length);
|
||||
if (nRead == 0)
|
||||
break;
|
||||
|
||||
// we must monitor the number of bytes actually written to the file. (mscott)
|
||||
if (destFile->write(m_ibuffer, nRead) != (PRInt32) nRead)
|
||||
{
|
||||
destFile->close();
|
||||
|
||||
// truncate destination file in case message was partially written
|
||||
// ### how to do this with a stream?
|
||||
destFileSpec.Truncate(newMsgPos);
|
||||
delete destFile;
|
||||
return NS_MSG_ERROR_WRITING_MAIL_FOLDER;
|
||||
}
|
||||
|
||||
length -= nRead;
|
||||
}
|
||||
|
||||
NS_ASSERTION(length == 0, "didn't read all of original message in filter move");
|
||||
delete destFile;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsParseNewMailState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
|
||||
nsIMsgDatabase *sourceDB,
|
||||
nsIMsgFolder *destIFolder,
|
||||
@ -1860,7 +1913,6 @@ nsresult nsParseNewMailState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
|
||||
nsIMsgWindow *msgWindow)
|
||||
{
|
||||
nsresult err = 0;
|
||||
nsIOFileStream *destFile;
|
||||
|
||||
// check if the destination is a real folder (by checking for null parent)
|
||||
// and if it can file messages (e.g., servers or news folders can't file messages).
|
||||
@ -1908,27 +1960,8 @@ nsresult nsParseNewMailState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
|
||||
return NS_MSG_FOLDER_UNREADABLE; // ### dmb
|
||||
}
|
||||
|
||||
PRUint32 messageOffset = 0;
|
||||
|
||||
mailHdr->GetMessageOffset(&messageOffset);
|
||||
m_inboxFileStream->seek(PR_SEEK_SET, messageOffset);
|
||||
int newMsgPos;
|
||||
|
||||
destFile = new nsIOFileStream(destFolderSpec, PR_WRONLY | PR_CREATE_FILE);
|
||||
|
||||
if (!destFile)
|
||||
{
|
||||
#ifdef DEBUG_bienvenu
|
||||
NS_ASSERTION(PR_FALSE, "out of memory");
|
||||
#endif
|
||||
if (destIFolder)
|
||||
destIFolder->ReleaseSemaphore (myISupports);
|
||||
destIFolder->ThrowAlertMsg("filterFolderWriteFailed", msgWindow);
|
||||
return NS_MSG_ERROR_WRITING_MAIL_FOLDER;
|
||||
}
|
||||
|
||||
destFile->seek(PR_SEEK_END, 0);
|
||||
newMsgPos = destFile->tell();
|
||||
m_inboxFileStream->seek(PR_SEEK_SET, m_curHdrOffset);
|
||||
PRUint32 newMsgPos = destFolderSpec.GetFileSize();
|
||||
|
||||
nsCOMPtr<nsIMsgLocalMailFolder> localFolder = do_QueryInterface(destIFolder);
|
||||
nsCOMPtr<nsIMsgDatabase> destMailDB;
|
||||
@ -1940,49 +1973,24 @@ nsresult nsParseNewMailState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
|
||||
NS_ASSERTION(destMailDB, "failed to open mail db parsing folder");
|
||||
// don't force upgrade in place - open the db here before we start writing to the
|
||||
// destination file because XP_Stat can return file size including bytes written...
|
||||
PRUint32 length;
|
||||
mailHdr->GetMessageSize(&length);
|
||||
|
||||
if (!m_ibuffer)
|
||||
m_ibuffer_size = 10240;
|
||||
m_ibuffer_fp = 0;
|
||||
|
||||
while (!m_ibuffer && (m_ibuffer_size >= 512))
|
||||
|
||||
PRUint32 messageLength;
|
||||
mailHdr->GetMessageSize(&messageLength);
|
||||
rv = AppendMsgFromFile(m_inboxFileStream, m_curHdrOffset, messageLength, destFolderSpec);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
m_ibuffer = (char *) PR_Malloc(m_ibuffer_size);
|
||||
if (m_ibuffer == nsnull)
|
||||
m_ibuffer_size /= 2;
|
||||
}
|
||||
NS_ASSERTION(m_ibuffer != nsnull, "couldn't get memory to move msg");
|
||||
while ((length > 0) && m_ibuffer)
|
||||
{
|
||||
PRUint32 nRead = m_inboxFileStream->read (m_ibuffer, length > m_ibuffer_size ? m_ibuffer_size : length);
|
||||
if (nRead == 0)
|
||||
break;
|
||||
|
||||
// we must monitor the number of bytes actually written to the file. (mscott)
|
||||
if (destFile->write(m_ibuffer, nRead) != (PRInt32) nRead)
|
||||
if (destMailDB)
|
||||
destMailDB->Close(PR_TRUE);
|
||||
|
||||
if (destIFolder)
|
||||
{
|
||||
destFile->close();
|
||||
|
||||
// truncate destination file in case message was partially written
|
||||
// ### how to do this with a stream?
|
||||
destFolderSpec.Truncate(newMsgPos);
|
||||
|
||||
if (destIFolder)
|
||||
destIFolder->ReleaseSemaphore(myISupports);
|
||||
|
||||
if (destMailDB)
|
||||
destMailDB->Close(PR_TRUE);
|
||||
destIFolder->ReleaseSemaphore(myISupports);
|
||||
destIFolder->ThrowAlertMsg("filterFolderWriteFailed", msgWindow);
|
||||
return NS_MSG_ERROR_WRITING_MAIL_FOLDER; // caller (ApplyFilters) currently ignores error conditions
|
||||
}
|
||||
|
||||
length -= nRead;
|
||||
return NS_MSG_ERROR_WRITING_MAIL_FOLDER;
|
||||
}
|
||||
|
||||
NS_ASSERTION(length == 0, "didn't read all of original message in filter move");
|
||||
|
||||
|
||||
PRBool movedMsgIsNew = PR_TRUE;
|
||||
// if we have made it this far then the message has successfully been written to the new folder
|
||||
// now add the header to the destMailDB.
|
||||
@ -2018,12 +2026,9 @@ nsresult nsParseNewMailState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
|
||||
destIFolder->SetHasNewMessages(PR_TRUE);
|
||||
|
||||
m_filterTargetFolders.AppendObject(destIFolder);
|
||||
|
||||
destFile->close();
|
||||
delete destFile;
|
||||
m_inboxFileStream->close();
|
||||
// How are we going to do this with a stream?
|
||||
nsresult truncRet = m_inboxFileSpec.Truncate(messageOffset);
|
||||
|
||||
nsresult truncRet = m_inboxFileSpec.Truncate(m_curHdrOffset);
|
||||
NS_ASSERTION(NS_SUCCEEDED(truncRet), "unable to truncate file");
|
||||
if (NS_FAILED(truncRet))
|
||||
destIFolder->ThrowAlertMsg("filterFolderTruncateFailed", msgWindow);
|
||||
@ -2037,8 +2042,7 @@ nsresult nsParseNewMailState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
|
||||
destIFolder->ReleaseSemaphore (myISupports);
|
||||
|
||||
// tell parser that we've truncated the Inbox
|
||||
mailHdr->GetMessageOffset(&messageOffset);
|
||||
nsParseMailMessageState::Init(messageOffset);
|
||||
nsParseMailMessageState::Init(m_curHdrOffset);
|
||||
|
||||
(void) localFolder->RefreshSizeOnDisk();
|
||||
if (destIFolder)
|
||||
|
@ -201,7 +201,6 @@ protected:
|
||||
nsCOMPtr<nsIMsgStatusFeedback> m_statusFeedback;
|
||||
|
||||
virtual PRInt32 PublishMsgHeader(nsIMsgWindow *msgWindow);
|
||||
virtual void FolderTypeSpecificTweakMsgHeader(nsIMsgDBHdr *tweakMe);
|
||||
void FreeBuffers();
|
||||
|
||||
// data
|
||||
@ -242,9 +241,14 @@ public:
|
||||
nsOutputFileStream *GetLogFile();
|
||||
virtual PRInt32 PublishMsgHeader(nsIMsgWindow *msgWindow);
|
||||
void GetMsgWindow(nsIMsgWindow **aMsgWindow);
|
||||
nsresult EndMsgDownload();
|
||||
nsresult EndMsgDownload();
|
||||
|
||||
nsresult AppendMsgFromFile(nsIOFileStream *fileStream, PRInt32 offset,
|
||||
PRUint32 length, nsFileSpec &destFileSpec);
|
||||
|
||||
virtual void ApplyFilters(PRBool *pMoved, nsIMsgWindow *msgWindow, PRUint32 msgOffset);
|
||||
|
||||
protected:
|
||||
virtual void ApplyFilters(PRBool *pMoved, nsIMsgWindow *msgWindow);
|
||||
virtual nsresult GetTrashFolder(nsIMsgFolder **pTrashFolder);
|
||||
virtual nsresult MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
|
||||
nsIMsgDatabase *sourceDB,
|
||||
@ -261,13 +265,16 @@ protected:
|
||||
|
||||
nsImapMoveCoalescer *m_moveCoalescer; // strictly owned by nsParseNewMailState;
|
||||
|
||||
PRBool m_msgMovedByFilter;
|
||||
nsIOFileStream *m_inboxFileStream;
|
||||
nsFileSpec m_inboxFileSpec;
|
||||
PRBool m_disableFilters;
|
||||
PRBool m_msgMovedByFilter;
|
||||
PRUint32 m_ibuffer_fp;
|
||||
char *m_ibuffer;
|
||||
PRUint32 m_ibuffer_size;
|
||||
// used for applying move filters, because in the case of using a temporary
|
||||
// download file, the offset/key in the msg hdr is not right.
|
||||
PRUint32 m_curHdrOffset;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1057,7 +1057,8 @@ nsPop3Protocol::Error(PRInt32 err_code)
|
||||
// so print out that error message!
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_url, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
// we handle POP3_TMP_DOWNLOAD_FAILED earlier...
|
||||
if (err_code != POP3_TMP_DOWNLOAD_FAILED && NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCOMPtr<nsIMsgWindow> msgWindow;
|
||||
nsCOMPtr<nsIPrompt> dialog;
|
||||
@ -1100,7 +1101,6 @@ nsPop3Protocol::Error(PRInt32 err_code)
|
||||
}
|
||||
m_pop3ConData->next_state = POP3_ERROR_DONE;
|
||||
m_pop3ConData->pause_for_read = PR_FALSE;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -3247,7 +3247,9 @@ nsPop3Protocol::HandleLine(char *line, PRUint32 line_length)
|
||||
// fixed to return errors)
|
||||
|
||||
if(NS_FAILED(rv))
|
||||
return(Error(POP3_MESSAGE_WRITE_ERROR));
|
||||
return(Error((rv == NS_MSG_ERROR_COPYING_FROM_TMP_DOWNLOAD)
|
||||
? POP3_TMP_DOWNLOAD_FAILED
|
||||
: POP3_MESSAGE_WRITE_ERROR));
|
||||
|
||||
m_pop3ConData->msg_closure = 0;
|
||||
return 0;
|
||||
|
@ -326,7 +326,8 @@ NS_IMETHODIMP nsPop3Service::NewURI(const nsACString &aSpec,
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
msgUrl->GetMessageHeader(getter_AddRefs(msgHdr));
|
||||
// we do this to get the account key
|
||||
localFolder->GetUidlFromFolder(&folderScanState, msgHdr);
|
||||
if (msgHdr)
|
||||
localFolder->GetUidlFromFolder(&folderScanState, msgHdr);
|
||||
if (!folderScanState.m_accountKey.IsEmpty())
|
||||
{
|
||||
nsCOMPtr<nsIMsgAccountManager> accountManager =
|
||||
|
@ -57,12 +57,23 @@
|
||||
#include "nsILineInputStream.h"
|
||||
#include "nsIPop3Protocol.h"
|
||||
#include "nsLocalMailFolder.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsSpecialSystemDirectory.h"
|
||||
#include "nsIMsgStringService.h"
|
||||
#include "nsIPrompt.h"
|
||||
#include "nsIPromptService.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDOMWindowInternal.h"
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsPop3Sink, nsIPop3Sink)
|
||||
|
||||
nsPop3Sink::nsPop3Sink()
|
||||
{
|
||||
m_authed = PR_FALSE;
|
||||
m_downloadingToTempFile = PR_FALSE;
|
||||
m_accountUrl = nsnull;
|
||||
m_biffState = 0;
|
||||
m_numNewMessages = 0;
|
||||
@ -277,12 +288,41 @@ nsPop3Sink::BeginMailDelivery(PRBool uidlDownload, nsIMsgWindow *aMsgWindow, PRB
|
||||
return NS_MSG_FOLDER_BUSY;
|
||||
|
||||
nsCOMPtr<nsIFileSpec> path;
|
||||
|
||||
m_folder->GetPath(getter_AddRefs(path));
|
||||
path->GetFileSpec(&fileSpec);
|
||||
m_outFileStream = new nsIOFileStream(fileSpec /*, PR_CREATE_FILE */);
|
||||
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> pPrefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
||||
if (pPrefBranch)
|
||||
pPrefBranch->GetBoolPref("mailnews.downloadToTempFile", &m_downloadingToTempFile);
|
||||
|
||||
if (m_downloadingToTempFile)
|
||||
{
|
||||
// need to create an nsIOFileStream from a temp file...
|
||||
nsCOMPtr <nsIFileSpec> tmpDownloadFile;
|
||||
nsSpecialSystemDirectory tmpFile(nsSpecialSystemDirectory::OS_TemporaryDirectory);
|
||||
tmpFile += "newmsg";
|
||||
|
||||
rv = NS_NewFileSpecWithSpec(tmpFile, getter_AddRefs(tmpDownloadFile));
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),"writing tmp pop3 download file: failed to append filename");
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = tmpDownloadFile->MakeUnique(); //need a unique tmp file to prevent dataloss in multiuser environment
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = tmpDownloadFile->GetFileSpec(&m_tmpDownloadFileSpec);
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
m_outFileStream = new nsIOFileStream(m_tmpDownloadFileSpec);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_outFileStream = new nsIOFileStream(fileSpec /*, PR_CREATE_FILE */);
|
||||
}
|
||||
// The following (!m_outFileStream etc) was added to make sure that we don't write somewhere
|
||||
// where for some reason or another we can't write too and lose the messages
|
||||
// where for some reason or another we can't write to and lose the messages
|
||||
// See bug 62480
|
||||
if (!m_outFileStream)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
@ -303,7 +343,7 @@ nsPop3Sink::BeginMailDelivery(PRBool uidlDownload, nsIMsgWindow *aMsgWindow, PRB
|
||||
rv = GetServerFolder(getter_AddRefs(serverFolder));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = m_newMailParser->Init(serverFolder, m_folder, fileSpec, m_outFileStream, aMsgWindow);
|
||||
rv = m_newMailParser->Init(serverFolder, m_folder, (m_downloadingToTempFile) ? m_tmpDownloadFileSpec : fileSpec, m_outFileStream, aMsgWindow);
|
||||
// if we failed to initialize the parser, then just don't use it!!!
|
||||
// we can still continue without one...
|
||||
|
||||
@ -312,11 +352,18 @@ nsPop3Sink::BeginMailDelivery(PRBool uidlDownload, nsIMsgWindow *aMsgWindow, PRB
|
||||
NS_IF_RELEASE(m_newMailParser);
|
||||
rv = NS_OK;
|
||||
}
|
||||
else
|
||||
else if (!m_downloadingToTempFile)
|
||||
{
|
||||
// Share the inbox fileStream so that moz-status-line flags can be set in the Inbox
|
||||
m_newMailParser->SetDBFolderStream(m_outFileStream);
|
||||
}
|
||||
else // if (m_downloadingToTempFile)
|
||||
{
|
||||
// Tell the parser to use the offset that will be in the dest folder,
|
||||
// not the temp folder, so that the msg hdr will start off with
|
||||
// the correct mdb oid
|
||||
m_newMailParser->SetEnvelopePos(fileSpec.GetFileSize());
|
||||
}
|
||||
|
||||
if (m_newMailParser)
|
||||
{
|
||||
@ -355,6 +402,9 @@ nsPop3Sink::EndMailDelivery(nsIPop3Protocol *protocol)
|
||||
m_outFileStream = 0;
|
||||
}
|
||||
|
||||
if (m_downloadingToTempFile)
|
||||
m_tmpDownloadFileSpec.Delete(PR_FALSE);
|
||||
|
||||
// tell the parser to mark the db valid *after* closing the mailbox.
|
||||
if (m_newMailParser)
|
||||
m_newMailParser->UpdateDBFolderInfo();
|
||||
@ -661,6 +711,49 @@ nsresult nsPop3Sink::WriteLineToMailbox(const char *buffer)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsPop3Sink::HandleTempDownloadFailed(nsIMsgWindow *msgWindow)
|
||||
{
|
||||
|
||||
nsCOMPtr<nsIMsgStringService> stringService = do_GetService(NS_MSG_POPSTRINGSERVICE_CONTRACTID);
|
||||
nsXPIDLString fromStr, subjectStr, confirmString;
|
||||
m_newMailParser->m_newMsgHdr->GetMime2DecodedSubject(getter_Copies(subjectStr));
|
||||
m_newMailParser->m_newMsgHdr->GetMime2DecodedAuthor(getter_Copies(fromStr));
|
||||
const PRUnichar *params[] = { fromStr.get(), subjectStr.get() };
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
nsresult rv = stringService->GetBundle(getter_AddRefs(bundle));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
bundle->FormatStringFromID(POP3_TMP_DOWNLOAD_FAILED, params, 2, getter_Copies(confirmString));
|
||||
nsCOMPtr<nsIDOMWindowInternal> parentWindow;
|
||||
nsCOMPtr<nsIPromptService> promptService = do_GetService("@mozilla.org/embedcomp/prompt-service;1");
|
||||
nsCOMPtr<nsIDocShell> docShell;
|
||||
if (msgWindow)
|
||||
{
|
||||
(void) msgWindow->GetRootDocShell(getter_AddRefs(docShell));
|
||||
parentWindow = do_QueryInterface(docShell);
|
||||
}
|
||||
PRBool confirmed = PR_FALSE;
|
||||
if (promptService && confirmString)
|
||||
{
|
||||
PRInt32 dlgResult = -1;
|
||||
rv = promptService->ConfirmEx(parentWindow, nsnull, confirmString,
|
||||
(nsIPromptService::BUTTON_TITLE_YES *
|
||||
nsIPromptService::BUTTON_POS_0) +
|
||||
(nsIPromptService::BUTTON_TITLE_NO *
|
||||
nsIPromptService::BUTTON_POS_1),
|
||||
nsnull,
|
||||
nsnull,
|
||||
nsnull,
|
||||
nsnull,
|
||||
nsnull,
|
||||
&dlgResult);
|
||||
m_newMailParser->m_newMsgHdr = nsnull;
|
||||
|
||||
return (dlgResult == 0) ? NS_OK : NS_MSG_ERROR_COPYING_FROM_TMP_DOWNLOAD;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPop3Sink::IncorporateComplete(nsIMsgWindow *aMsgWindow, PRInt32 aSize)
|
||||
{
|
||||
@ -690,7 +783,70 @@ nsPop3Sink::IncorporateComplete(nsIMsgWindow *aMsgWindow, PRInt32 aSize)
|
||||
if (!aSize && localFolder)
|
||||
(void) localFolder->DeleteDownloadMsg(hdr, &doSelect);
|
||||
|
||||
m_newMailParser->PublishMsgHeader(aMsgWindow);
|
||||
if (m_downloadingToTempFile)
|
||||
{
|
||||
PRBool moved = PR_FALSE;
|
||||
// close file to give virus checkers a chance to do their thing...
|
||||
m_outFileStream->flush();
|
||||
m_outFileStream->close();
|
||||
m_newMailParser->FinishHeader();
|
||||
// need to re-open the inbox file stream.
|
||||
if (!m_tmpDownloadFileSpec.Exists())
|
||||
return HandleTempDownloadFailed(aMsgWindow);
|
||||
|
||||
m_outFileStream->Open(m_tmpDownloadFileSpec, (PR_RDWR | PR_CREATE_FILE));
|
||||
|
||||
m_newMailParser->ApplyFilters(&moved, aMsgWindow, 0);
|
||||
if (!moved)
|
||||
{
|
||||
if (m_outFileStream->is_open())
|
||||
{
|
||||
nsFileSpec destFolderSpec;
|
||||
|
||||
nsCOMPtr<nsIFileSpec> path;
|
||||
|
||||
m_folder->GetPath(getter_AddRefs(path));
|
||||
path->GetFileSpec(&destFolderSpec);
|
||||
PRUint32 newMsgPos = destFolderSpec.GetFileSize();
|
||||
PRUint32 msgSize;
|
||||
hdr->GetMessageSize(&msgSize);
|
||||
if (msgSize > m_tmpDownloadFileSpec.GetFileSize())
|
||||
rv = NS_MSG_ERROR_WRITING_MAIL_FOLDER;
|
||||
else
|
||||
rv = m_newMailParser->AppendMsgFromFile(m_outFileStream, 0, msgSize, destFolderSpec);
|
||||
if (NS_FAILED(rv))
|
||||
return HandleTempDownloadFailed(aMsgWindow);
|
||||
|
||||
// if we have made it this far then the message has successfully been written to the new folder
|
||||
// now add the header to the destMailDB.
|
||||
if (NS_SUCCEEDED(rv) && m_newMailParser->m_mailDB)
|
||||
{
|
||||
PRUint32 newFlags;
|
||||
hdr->GetFlags(&newFlags);
|
||||
if (! (newFlags & MSG_FLAG_READ))
|
||||
{
|
||||
hdr->OrFlags(MSG_FLAG_NEW, &newFlags);
|
||||
m_newMailParser->m_mailDB->AddToNewList(newMsgPos);
|
||||
}
|
||||
m_newMailParser->m_mailDB->AddNewHdrToDB(hdr, PR_TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return HandleTempDownloadFailed(aMsgWindow);
|
||||
// need to give an error here.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// cleanup after mailHdr in source DB because we moved the message.
|
||||
m_newMailParser->m_mailDB->RemoveHeaderMdbRow(hdr);
|
||||
}
|
||||
m_newMailParser->m_newMsgHdr = nsnull;
|
||||
m_outFileStream->close(); // close so we can delete temp file.
|
||||
m_tmpDownloadFileSpec.Delete(PR_FALSE);
|
||||
|
||||
}
|
||||
if (aSize)
|
||||
hdr->SetUint32Property("onlineSize", aSize);
|
||||
|
||||
|
@ -70,6 +70,7 @@ protected:
|
||||
|
||||
nsresult WriteLineToMailbox(const char *buffer);
|
||||
nsresult ReleaseFolderLock();
|
||||
nsresult HandleTempDownloadFailed(nsIMsgWindow *msgWindow);
|
||||
|
||||
PRBool m_authed;
|
||||
PRInt64 m_msgOffset;
|
||||
@ -89,6 +90,8 @@ protected:
|
||||
#endif
|
||||
nsIOFileStream* m_outFileStream;
|
||||
PRBool m_buildMessageUri;
|
||||
PRBool m_downloadingToTempFile;
|
||||
nsFileSpec m_tmpDownloadFileSpec;
|
||||
nsCString m_messageUri;
|
||||
nsXPIDLCString m_baseMessageUri;
|
||||
nsXPIDLCString m_accountKey;
|
||||
|
Loading…
x
Reference in New Issue
Block a user