diff --git a/mailnews/base/public/nsIMsgFolder.idl b/mailnews/base/public/nsIMsgFolder.idl index dd26b50e96b..d8856eef5b7 100644 --- a/mailnews/base/public/nsIMsgFolder.idl +++ b/mailnews/base/public/nsIMsgFolder.idl @@ -71,7 +71,7 @@ typedef long nsMsgBiffState; // enumerated type for determining if a message has been replied to, forwarded, etc. typedef long nsMsgDispositionState; -[scriptable, uuid(c295ac49-5623-4aea-b78a-09e37c5a3948)] +[scriptable, uuid(63b5d816-06e8-4a86-918c-56de10293f58)] interface nsIMsgFolder : nsICollection { const nsMsgBiffState nsMsgBiffState_NewMail = 0; // User has new mail waiting. @@ -472,4 +472,5 @@ const nsMsgBiffState nsMsgBiffState_Unknown = 2; // We dunno whether there is ne in long aLength, in nsIOutputStream outputStream); void copyDataDone(); void setJunkScoreForMessages(in nsISupportsArray aMessages, in string aJunkScore); + void applyRetentionSettings(); }; diff --git a/mailnews/base/src/nsMsgPurgeService.cpp b/mailnews/base/src/nsMsgPurgeService.cpp index 7bd8bfa7bec..3d99840afb3 100644 --- a/mailnews/base/src/nsMsgPurgeService.cpp +++ b/mailnews/base/src/nsMsgPurgeService.cpp @@ -22,6 +22,7 @@ * Contributor(s): * Navin Gupta (Original Developer) * Seth Spitzer + * David Bienvenu * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -59,6 +60,7 @@ #include "nsIPrefBranch.h" #include "nsIPrefService.h" #include "prlog.h" +#include "nsMsgFolderFlags.h" static PRLogModuleInfo *MsgPurgeLogModule = nsnull; @@ -73,20 +75,17 @@ void OnPurgeTimer(nsITimer *timer, void *aPurgeService) nsMsgPurgeService::nsMsgPurgeService() { mHaveShutdown = PR_FALSE; - mMinDelayBetweenPurges = 480; // never purge a junk folder more than once every 8 hours (60 min/hour * 8 hours) + mMinDelayBetweenPurges = 480; // never purge a folder more than once every 8 hours (60 min/hour * 8 hours) mPurgeTimerInterval = 5; // fire the purge timer every 5 minutes, starting 5 minutes after the service is created (when we load accounts) } nsMsgPurgeService::~nsMsgPurgeService() { - if (mPurgeTimer) { + if (mPurgeTimer) mPurgeTimer->Cancel(); - } if(!mHaveShutdown) - { Shutdown(); - } } NS_IMETHODIMP nsMsgPurgeService::Init() @@ -102,15 +101,13 @@ NS_IMETHODIMP nsMsgPurgeService::Init() { PRInt32 min_delay; rv = prefBranch->GetIntPref("mail.purge.min_delay", &min_delay); - if (NS_SUCCEEDED(rv) && min_delay) { + if (NS_SUCCEEDED(rv) && min_delay) mMinDelayBetweenPurges = min_delay; - } PRInt32 purge_timer_interval; rv = prefBranch->GetIntPref("mail.purge.timer_interval", &purge_timer_interval); - if (NS_SUCCEEDED(rv) && purge_timer_interval) { + if (NS_SUCCEEDED(rv) && purge_timer_interval) mPurgeTimerInterval = purge_timer_interval; - } } PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("mail.purge.min_delay=%d minutes",mMinDelayBetweenPurges)); @@ -156,7 +153,15 @@ nsresult nsMsgPurgeService::SetupNextPurge() return NS_OK; } -// This is the function that looks for the first folder to purge +// This is the function that looks for the first folder to purge. It also +// applies retention settings to any folder that hasn't had retention settings +// applied in mMinDelayBetweenPurges minutes (default, 8 hours). +// However, if we've spent more than .5 seconds in this loop, don't +// apply any more retention settings because it might lock up the UI. +// This might starve folders later on in the hierarchy, since we always +// start at the top, but since we also apply retention settings when you +// open a folder, or when you compact all folders, I think this will do +// for now, until we have a cleanup on shutdown architecture. nsresult nsMsgPurgeService::PerformPurge() { PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("performing purge")); @@ -165,6 +170,7 @@ nsresult nsMsgPurgeService::PerformPurge() nsCOMPtr accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv,rv); + PRBool keepApplyingRetentionSettings = PR_TRUE; nsCOMPtr allServers; rv = accountManager->GetAllServers(getter_AddRefs(allServers)); @@ -174,14 +180,87 @@ nsresult nsMsgPurgeService::PerformPurge() rv = allServers->Count(&numServers); PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("%d servers", numServers)); nsCOMPtr folderToPurge; + PRIntervalTime startTime = PR_IntervalNow(); PRInt32 purgeIntervalToUse; nsTime oldestPurgeTime = 0; // we're going to pick the least-recently purged folder + + // apply retention settings to folders that haven't had retention settings + // applied in mMinDelayBetweenPurges minutes (default 8 hours) + // Because we get last purge time from the folder cache, + // this code won't open db's for folders until it decides it needs + // to apply retention settings, and since nsIMsgFolder::ApplyRetentionSettings + // will close any db's it opens, this code won't leave db's open. for (PRUint32 serverIndex=0; serverIndex < numServers; serverIndex++) { nsCOMPtr server = do_QueryElementAt(allServers, serverIndex, &rv); if (NS_SUCCEEDED(rv) && server) { + if (keepApplyingRetentionSettings) + { + nsCOMPtr rootFolder; + rv = server->GetRootFolder(getter_AddRefs(rootFolder)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr childFolders = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + rv = rootFolder->ListDescendents(childFolders); + + PRUint32 cnt =0; + childFolders->Count(&cnt); + + nsCOMPtr supports; + nsCOMPtr urlListener; + nsCOMPtr childFolder; + + for (PRUint32 index = 0; index < cnt; index++) + { + childFolder = do_QueryElementAt(childFolders, index); + if (childFolder) + { + PRUint32 folderFlags; + (void) childFolder->GetFlags(&folderFlags); + if (folderFlags & MSG_FOLDER_FLAG_VIRTUAL) + continue; + nsTime curFolderLastPurgeTime=0; + nsXPIDLCString curFolderLastPurgeTimeString, curFolderUri; + rv = childFolder->GetStringProperty("LastPurgeTime", getter_Copies(curFolderLastPurgeTimeString)); + if (NS_FAILED(rv)) + continue; // it is ok to fail, go on to next folder + + if (!curFolderLastPurgeTimeString.IsEmpty()) + { + PRInt64 theTime; + PR_ParseTimeString(curFolderLastPurgeTimeString.get(), PR_FALSE, &theTime); + curFolderLastPurgeTime = theTime; + } + + childFolder->GetURI(getter_Copies(curFolderUri)); + PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("%s curFolderLastPurgeTime=%s (if blank, then never)", curFolderUri.get(), curFolderLastPurgeTimeString.get())); + + // check if this folder is due to purge + // has to have been purged at least mMinDelayBetweenPurges minutes ago + // we don't want to purge the folders all the time - once a day is good enough + nsInt64 minDelayBetweenPurges(mMinDelayBetweenPurges); + nsInt64 microSecondsPerMinute(60000000); + nsTime nextPurgeTime = curFolderLastPurgeTime + (minDelayBetweenPurges * microSecondsPerMinute); + nsTime currentTime; // nsTime defaults to PR_Now + if (nextPurgeTime < currentTime) + { + PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("purging %s", curFolderUri.get())); + childFolder->ApplyRetentionSettings(); + } + PRIntervalTime elapsedTime; + LL_SUB(elapsedTime, PR_IntervalNow(), startTime); + // check if more than 500 milliseconds have elapsed in this purge process + if (PR_IntervalToMilliseconds(elapsedTime) > 500) + { + keepApplyingRetentionSettings = PR_FALSE; + break; + } + } + } + } nsXPIDLCString type; nsresult rv = server->GetType(getter_Copies(type)); NS_ENSURE_SUCCESS(rv, rv); @@ -192,7 +271,6 @@ nsresult nsMsgPurgeService::PerformPurge() nsCOMPtr protocolInfo = do_GetService(contractid.get(), &rv); NS_ENSURE_SUCCESS(rv, PR_FALSE); - nsXPIDLCString realHostName; server->GetRealHostName(getter_Copies(realHostName)); diff --git a/mailnews/base/util/nsMsgDBFolder.cpp b/mailnews/base/util/nsMsgDBFolder.cpp index 493033797f1..a171e7b6a6f 100644 --- a/mailnews/base/util/nsMsgDBFolder.cpp +++ b/mailnews/base/util/nsMsgDBFolder.cpp @@ -1346,6 +1346,9 @@ nsMsgDBFolder::GetRetentionSettings(nsIMsgRetentionSettings **settings) NS_IMETHODIMP nsMsgDBFolder::SetRetentionSettings(nsIMsgRetentionSettings *settings) { m_retentionSettings = settings; + GetDatabase(nsnull); + if (mDatabase) + mDatabase->SetMsgRetentionSettings(settings); return NS_OK; } @@ -4322,6 +4325,40 @@ nsMsgDBFolder::SetJunkScoreForMessages(nsISupportsArray *aMessages, const char * return rv; } +NS_IMETHODIMP +nsMsgDBFolder::ApplyRetentionSettings() +{ + return ApplyRetentionSettings(PR_TRUE); +} + +nsresult nsMsgDBFolder::ApplyRetentionSettings(PRBool deleteViaFolder) +{ + if (mFlags & MSG_FOLDER_FLAG_VIRTUAL) // ignore virtual folders. + return NS_OK; + nsresult rv; + PRBool weOpenedDB = PR_FALSE; + if (!mDatabase) + { + rv = GetDatabase(nsnull); + NS_ENSURE_SUCCESS(rv, rv); + weOpenedDB = PR_TRUE; + } + if (mDatabase) + { + nsCOMPtr retentionSettings; + rv = GetRetentionSettings(getter_AddRefs(retentionSettings)); + if (NS_SUCCEEDED(rv)) + rv = mDatabase->ApplyRetentionSettings(retentionSettings, deleteViaFolder); + // we don't want applying retention settings to keep the db open, because + // if we try to purge a bunch of folders, that will leave the dbs all open. + // So if we opened the db, close it. + if (weOpenedDB) + CloseDBIfFolderNotOpen(); + } + return rv; +} + + NS_IMETHODIMP nsMsgDBFolder::DeleteMessages(nsISupportsArray *messages, nsIMsgWindow *msgWindow, diff --git a/mailnews/base/util/nsMsgDBFolder.h b/mailnews/base/util/nsMsgDBFolder.h index dcbae9678eb..bfe8f84d4d1 100644 --- a/mailnews/base/util/nsMsgDBFolder.h +++ b/mailnews/base/util/nsMsgDBFolder.h @@ -152,6 +152,7 @@ protected: nsresult MsgFitsDownloadCriteria(nsMsgKey msgKey, PRBool *result); nsresult GetPromptPurgeThreshold(PRBool *aPrompt); nsresult GetPurgeThreshold(PRInt32 *aThreshold); + nsresult ApplyRetentionSettings(PRBool deleteViaFolder); nsresult PerformBiffNotifications(void); // if there are new, non spam messages, do biff nsresult CloseDBIfFolderNotOpen(); @@ -159,6 +160,7 @@ protected: virtual nsresult SpamFilterClassifyMessage(const char *aURI, nsIMsgWindow *aMsgWindow, nsIJunkMailPlugin *aJunkMailPlugin); virtual nsresult SpamFilterClassifyMessages(const char **aURIArray, PRUint32 aURICount, nsIMsgWindow *aMsgWindow, nsIJunkMailPlugin *aJunkMailPlugin); + protected: nsCOMPtr mDatabase; nsCString mCharset; diff --git a/mailnews/db/msgdb/public/nsIMsgDatabase.idl b/mailnews/db/msgdb/public/nsIMsgDatabase.idl index edc6954d2c3..38674f86d24 100644 --- a/mailnews/db/msgdb/public/nsIMsgDatabase.idl +++ b/mailnews/db/msgdb/public/nsIMsgDatabase.idl @@ -53,6 +53,7 @@ interface nsIDBFolderInfo; interface nsIMsgOfflineImapOperation; interface nsIMsgFolder; interface nsIOFileStream; +interface nsIUrlListener; [ptr] native octetPtr(PRUint8); @@ -63,9 +64,9 @@ typedef unsigned long nsMsgRetainByPreference; interface nsIMsgRetentionSettings : nsISupports { - const unsigned long nsMsgRetainAll = 1; - const unsigned long nsMsgRetainByAge = 2; - const unsigned long nsMsgRetainByNumHeaders = 3; + const unsigned long nsMsgRetainAll = 1; + const unsigned long nsMsgRetainByAge = 2; + const unsigned long nsMsgRetainByNumHeaders = 3; attribute boolean useServerDefaults; attribute nsMsgRetainByPreference retainByPreference; @@ -86,8 +87,8 @@ interface nsIMsgDownloadSettings : nsISupports { attribute boolean useServerDefaults; attribute boolean downloadByDate; - attribute boolean downloadUnreadOnly; - attribute unsigned long ageLimitOfMsgsToDownload; + attribute boolean downloadUnreadOnly; + attribute unsigned long ageLimitOfMsgsToDownload; }; typedef long nsMsgDBCommit; @@ -116,7 +117,7 @@ interface nsIMsgDBService : nsISupports void unregisterPendingListener(in nsIDBChangeListener aListener); }; -[scriptable, uuid(f667dcb8-5aae-4e71-8559-2a48d7e508cd)] +[scriptable, uuid(1a706802-8121-4f91-a302-6e1f9a13204b)] interface nsIMsgDatabase : nsIDBChangeAnnouncer { void Open(in nsIFileSpec aFolderName, in boolean aCreate, in boolean aLeaveInvalidDB); @@ -237,8 +238,11 @@ interface nsIMsgDatabase : nsIDBChangeAnnouncer { readonly attribute nsMsgKey FirstNew; attribute nsIMsgRetentionSettings msgRetentionSettings; - // purge unwanted message headers and/or bodies - void ApplyRetentionSettings(in nsIMsgRetentionSettings msgRetentionSettings); + // purge unwanted message headers and/or bodies. If deleteViaFolder is + // true, we'll call nsIMsgFolder::DeleteMessages to delete the messages. + // Otherwise, we'll just delete them from the db. + void applyRetentionSettings(in nsIMsgRetentionSettings aMsgRetentionSettings, + in boolean aDeleteViaFolder); attribute nsIMsgDownloadSettings msgDownloadSettings; diff --git a/mailnews/db/msgdb/public/nsMsgDatabase.h b/mailnews/db/msgdb/public/nsMsgDatabase.h index c6d3da6101b..9e304bec709 100644 --- a/mailnews/db/msgdb/public/nsMsgDatabase.h +++ b/mailnews/db/msgdb/public/nsMsgDatabase.h @@ -219,8 +219,10 @@ protected: nsCOMPtr m_retentionSettings; nsCOMPtr m_downloadSettings; - nsresult PurgeMessagesOlderThan(PRUint32 daysToKeepHdrs, PRBool keepUnreadMessagesOnly); - nsresult PurgeExcessMessages(PRUint32 numHeadersToKeep, PRBool keepUnreadMessagesOnly); + nsresult PurgeMessagesOlderThan(PRUint32 daysToKeepHdrs, PRBool keepUnreadMessagesOnly, + nsISupportsArray *hdrsToDelete); + nsresult PurgeExcessMessages(PRUint32 numHeadersToKeep, PRBool keepUnreadMessagesOnly, + nsISupportsArray *hdrsToDelete); // mdb bookkeeping stuff virtual nsresult InitExistingDB(); diff --git a/mailnews/db/msgdb/src/nsMsgDatabase.cpp b/mailnews/db/msgdb/src/nsMsgDatabase.cpp index b10716d4eb0..cd7850b3bb6 100644 --- a/mailnews/db/msgdb/src/nsMsgDatabase.cpp +++ b/mailnews/db/msgdb/src/nsMsgDatabase.cpp @@ -4169,6 +4169,7 @@ NS_IMETHODIMP nsMsgDatabase::SetMsgRetentionSettings(nsIMsgRetentionSettings *re PRBool keepUnreadMessagesOnly; PRUint32 daysToKeepBodies; PRBool cleanupBodiesByDays; + PRBool useServerDefaults; rv = retentionSettings->GetRetainByPreference(&retainByPreference); NS_ENSURE_SUCCESS(rv, rv); @@ -4180,7 +4181,8 @@ NS_IMETHODIMP nsMsgDatabase::SetMsgRetentionSettings(nsIMsgRetentionSettings *re NS_ENSURE_SUCCESS(rv, rv); rv = retentionSettings->GetDaysToKeepBodies(&daysToKeepBodies); NS_ENSURE_SUCCESS(rv, rv); - rv = retentionSettings->GetCleanupBodiesByDays(&cleanupBodiesByDays); + (void) retentionSettings->GetCleanupBodiesByDays(&cleanupBodiesByDays); + (void) retentionSettings->GetUseServerDefaults(&useServerDefaults); // need to write this to the db. We'll just use the dbfolderinfo to write properties. m_dbFolderInfo->SetUint32Property("retainBy", retainByPreference); m_dbFolderInfo->SetUint32Property("daysToKeepHdrs", daysToKeepHdrs); @@ -4188,7 +4190,9 @@ NS_IMETHODIMP nsMsgDatabase::SetMsgRetentionSettings(nsIMsgRetentionSettings *re m_dbFolderInfo->SetUint32Property("daysToKeepBodies", daysToKeepBodies); m_dbFolderInfo->SetUint32Property("keepUnreadOnly", (keepUnreadMessagesOnly) ? 1 : 0); m_dbFolderInfo->SetBooleanProperty("cleanupBodies", cleanupBodiesByDays); + m_dbFolderInfo->SetBooleanProperty("useServerDefaults", useServerDefaults); } + Commit(nsMsgDBCommitType::kLargeCommit); return NS_OK; } @@ -4293,17 +4297,24 @@ NS_IMETHODIMP nsMsgDatabase::GetMsgDownloadSettings(nsIMsgDownloadSettings **dow return NS_OK; } -NS_IMETHODIMP nsMsgDatabase::ApplyRetentionSettings(nsIMsgRetentionSettings *msgRetentionSettings) +NS_IMETHODIMP nsMsgDatabase::ApplyRetentionSettings(nsIMsgRetentionSettings *aMsgRetentionSettings, + PRBool aDeleteViaFolder) { - NS_ENSURE_ARG_POINTER(msgRetentionSettings); + NS_ENSURE_ARG_POINTER(aMsgRetentionSettings); nsresult rv = NS_OK; + nsCOMPtr msgHdrsToDelete; + if (aDeleteViaFolder) + { + msgHdrsToDelete = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + } nsMsgRetainByPreference retainByPreference; PRUint32 daysToKeepHdrs = 0; PRUint32 numHeadersToKeep = 0; PRBool keepUnreadMessagesOnly = PR_FALSE; - msgRetentionSettings->GetRetainByPreference(&retainByPreference); - msgRetentionSettings->GetKeepUnreadMessagesOnly(&keepUnreadMessagesOnly); + aMsgRetentionSettings->GetRetainByPreference(&retainByPreference); + aMsgRetentionSettings->GetKeepUnreadMessagesOnly(&keepUnreadMessagesOnly); switch (retainByPreference) { @@ -4312,20 +4323,39 @@ NS_IMETHODIMP nsMsgDatabase::ApplyRetentionSettings(nsIMsgRetentionSettings *msg { mdb_count numHdrs = 0; m_mdbAllMsgHeadersTable->GetCount(GetEnv(), &numHdrs); - return PurgeExcessMessages(numHdrs, PR_TRUE); + rv = PurgeExcessMessages(numHdrs, PR_TRUE, msgHdrsToDelete); } break; case nsIMsgRetentionSettings::nsMsgRetainByAge: - msgRetentionSettings->GetDaysToKeepHdrs(&daysToKeepHdrs); - return PurgeMessagesOlderThan(daysToKeepHdrs, keepUnreadMessagesOnly); + aMsgRetentionSettings->GetDaysToKeepHdrs(&daysToKeepHdrs); + rv = PurgeMessagesOlderThan(daysToKeepHdrs, keepUnreadMessagesOnly, msgHdrsToDelete); case nsIMsgRetentionSettings::nsMsgRetainByNumHeaders: - msgRetentionSettings->GetNumHeadersToKeep(&numHeadersToKeep); - return PurgeExcessMessages(numHeadersToKeep, keepUnreadMessagesOnly); + aMsgRetentionSettings->GetNumHeadersToKeep(&numHeadersToKeep); + rv = PurgeExcessMessages(numHeadersToKeep, keepUnreadMessagesOnly, msgHdrsToDelete); + } + if (m_folder) + { + // update the time we attempted to purge this folder + char dateBuf[100]; + dateBuf[0] = '\0'; + PRExplodedTime exploded; + PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &exploded); + PR_FormatTimeUSEnglish(dateBuf, sizeof(dateBuf), "%a %b %d %H:%M:%S %Y", &exploded); + m_folder->SetStringProperty("LastPurgeTime", dateBuf); + } + if (msgHdrsToDelete) + { + PRUint32 count; + msgHdrsToDelete->Count(&count); + if (count > 0) + rv = m_folder->DeleteMessages(msgHdrsToDelete, nsnull, PR_TRUE, PR_FALSE, nsnull, PR_FALSE); } return rv; } -nsresult nsMsgDatabase::PurgeMessagesOlderThan(PRUint32 daysToKeepHdrs, PRBool keepUnreadMessagesOnly) +nsresult nsMsgDatabase::PurgeMessagesOlderThan(PRUint32 daysToKeepHdrs, + PRBool keepUnreadMessagesOnly, + nsISupportsArray *hdrsToDelete) { nsresult rv = NS_OK; nsMsgHdr *pHeader; @@ -4377,20 +4407,26 @@ nsresult nsMsgDatabase::PurgeMessagesOlderThan(PRUint32 daysToKeepHdrs, PRBool k nsMsgKey msgKey; pHeader->GetMessageKey(&msgKey); keysToDelete.Add(msgKey); + if (hdrsToDelete) + hdrsToDelete->AppendElement(pHeader); } NS_RELEASE(pHeader); } - DeleteMessages(&keysToDelete, nsnull); + if (!hdrsToDelete) + { + DeleteMessages(&keysToDelete, nsnull); - if (keysToDelete.GetSize() > 10) // compress commit if we deleted more than 10 - Commit(nsMsgDBCommitType::kCompressCommit); - else if (keysToDelete.GetSize() > 0) - Commit(nsMsgDBCommitType::kLargeCommit); + if (keysToDelete.GetSize() > 10) // compress commit if we deleted more than 10 + Commit(nsMsgDBCommitType::kCompressCommit); + else if (keysToDelete.GetSize() > 0) + Commit(nsMsgDBCommitType::kLargeCommit); + } return rv; } -nsresult nsMsgDatabase::PurgeExcessMessages(PRUint32 numHeadersToKeep, PRBool keepUnreadMessagesOnly) +nsresult nsMsgDatabase::PurgeExcessMessages(PRUint32 numHeadersToKeep, PRBool keepUnreadMessagesOnly, + nsISupportsArray *hdrsToDelete) { nsresult rv = NS_OK; nsMsgHdr *pHeader; @@ -4433,18 +4469,23 @@ nsresult nsMsgDatabase::PurgeExcessMessages(PRUint32 numHeadersToKeep, PRBool ke pHeader->GetMessageKey(&msgKey); keysToDelete.Add(msgKey); numHdrs--; + if (hdrsToDelete) + hdrsToDelete->AppendElement(pHeader); } NS_RELEASE(pHeader); } - PRInt32 numKeysToDelete = keysToDelete.GetSize(); - if (numKeysToDelete > 0) + if (!hdrsToDelete) { - DeleteMessages(&keysToDelete, nsnull); - if (numKeysToDelete > 10) // compress commit if we deleted more than 10 - Commit(nsMsgDBCommitType::kCompressCommit); - else - Commit(nsMsgDBCommitType::kLargeCommit); + PRInt32 numKeysToDelete = keysToDelete.GetSize(); + if (numKeysToDelete > 0) + { + DeleteMessages(&keysToDelete, nsnull); + if (numKeysToDelete > 10) // compress commit if we deleted more than 10 + Commit(nsMsgDBCommitType::kCompressCommit); + else + Commit(nsMsgDBCommitType::kLargeCommit); + } } return rv; } diff --git a/mailnews/imap/src/nsImapMailFolder.cpp b/mailnews/imap/src/nsImapMailFolder.cpp index 3dda68da901..07c7b4dd893 100644 --- a/mailnews/imap/src/nsImapMailFolder.cpp +++ b/mailnews/imap/src/nsImapMailFolder.cpp @@ -1221,10 +1221,19 @@ NS_IMETHODIMP nsImapMailFolder::GetNoSelect(PRBool *aResult) NS_IMETHODIMP nsImapMailFolder::Compact(nsIUrlListener *aListener, nsIMsgWindow *aMsgWindow) { nsresult rv; + + rv = GetDatabase(nsnull); + // now's a good time to apply the retention settings. If we do delete any + // messages, the expunge is going to have to wait until the delete to + // finish before it can run, but the multiple-connection protection code + // should handle that. + if (mDatabase) + ApplyRetentionSettings(); + // compact offline store, if folder configured for offline use. // for now, check aMsgWindow because not having aMsgWindow means // we're doing a compact at shut-down. TEMPORARY HACK - if (aMsgWindow && mFlags & MSG_FOLDER_FLAG_OFFLINE) + if (aMsgWindow && mFlags & MSG_FOLDER_FLAG_OFFLINE) CompactOfflineStore(aMsgWindow); nsCOMPtr imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv); diff --git a/mailnews/local/src/nsLocalMailFolder.cpp b/mailnews/local/src/nsLocalMailFolder.cpp index c40b8ae99cd..9831aeb2eff 100644 --- a/mailnews/local/src/nsLocalMailFolder.cpp +++ b/mailnews/local/src/nsLocalMailFolder.cpp @@ -671,6 +671,8 @@ nsMsgLocalMailFolder::UpdateFolder(nsIMsgWindow *aWindow) PRBool filtersRun; PRBool hasNewMessages; GetHasNewMessages(&hasNewMessages); + if (mDatabase) + ApplyRetentionSettings(); // if we have new messages, try the filter plugins. if (NS_SUCCEEDED(rv) && hasNewMessages) (void) CallFilterPlugins(aWindow, &filtersRun); @@ -2472,6 +2474,10 @@ void nsMsgLocalMailFolder::CopyPropertiesToMsgHdr(nsIMsgDBHdr *destHdr, nsIMsgDB destHdr->SetStringProperty("junkscore", sourceJunkScore); srcHdr->GetStringProperty("junkscoreorigin", getter_Copies(sourceJunkScore)); destHdr->SetStringProperty("junkscoreorigin", sourceJunkScore); + + nsMsgLabelValue label = 0; + srcHdr->GetLabel(&label); + destHdr->SetLabel(label); } @@ -2585,7 +2591,7 @@ NS_IMETHODIMP nsMsgLocalMailFolder::EndCopy(PRBool copySucceeded) nsresult result = mCopyState->m_parseMsgState->GetNewMsgHdr(getter_AddRefs(newHdr)); if (NS_SUCCEEDED(result) && newHdr) { - // need to copy junk score from mCopyState->m_message to newHdr. + // need to copy junk score and label from mCopyState->m_message to newHdr. if (mCopyState->m_message) CopyPropertiesToMsgHdr(newHdr, mCopyState->m_message); msgDb->AddNewHdrToDB(newHdr, PR_TRUE); diff --git a/mailnews/news/src/nsNewsFolder.cpp b/mailnews/news/src/nsNewsFolder.cpp index 3cb6be1c908..f9d57499e23 100644 --- a/mailnews/news/src/nsNewsFolder.cpp +++ b/mailnews/news/src/nsNewsFolder.cpp @@ -421,7 +421,7 @@ nsMsgNewsFolder::UpdateFolder(nsIMsgWindow *aWindow) nsCOMPtr retentionSettings; nsresult rv = GetRetentionSettings(getter_AddRefs(retentionSettings)); if (NS_SUCCEEDED(rv)) - rv = mDatabase->ApplyRetentionSettings(retentionSettings); + rv = mDatabase->ApplyRetentionSettings(retentionSettings, PR_FALSE); } rv = AutoCompact(aWindow); NS_ENSURE_SUCCESS(rv,rv); @@ -893,7 +893,7 @@ NS_IMETHODIMP nsMsgNewsFolder::GetSizeOnDisk(PRUint32 *size) return NS_ERROR_NOT_IMPLEMENTED; } -/* this is news, so remember that DeleteMessage is really CANCEL */ +/* this is news, so remember that DeleteMessage is really CANCEL. */ NS_IMETHODIMP nsMsgNewsFolder::DeleteMessages(nsISupportsArray *messages, nsIMsgWindow *aMsgWindow, PRBool deleteStorage, PRBool isMove, @@ -1780,15 +1780,17 @@ NS_IMETHODIMP nsMsgNewsFolder::Compact(nsIUrlListener *aListener, nsIMsgWindow * rv = GetDatabase(nsnull); if (mDatabase) - { - nsCOMPtr retentionSettings; - rv = GetRetentionSettings(getter_AddRefs(retentionSettings)); - if (NS_SUCCEEDED(rv)) - rv = mDatabase->ApplyRetentionSettings(retentionSettings); - } + ApplyRetentionSettings(); return rv; } +NS_IMETHODIMP +nsMsgNewsFolder::ApplyRetentionSettings() +{ + return nsMsgDBFolder::ApplyRetentionSettings(PR_FALSE); +} + + NS_IMETHODIMP nsMsgNewsFolder::GetMessageIdForKey(nsMsgKey key, char **result) { nsresult rv; diff --git a/mailnews/news/src/nsNewsFolder.h b/mailnews/news/src/nsNewsFolder.h index 3342a51a905..45b18c9a8d9 100644 --- a/mailnews/news/src/nsNewsFolder.h +++ b/mailnews/news/src/nsNewsFolder.h @@ -119,6 +119,7 @@ public: NS_IMETHOD GetFilterList(nsIMsgWindow *aMsgWindow, nsIMsgFilterList **aFilterList); NS_IMETHOD SetFilterList(nsIMsgFilterList *aFilterList); + NS_IMETHOD ApplyRetentionSettings(); // for nsMsgLineBuffer virtual PRInt32 HandleLine(char *line, PRUint32 line_size);