diff --git a/mailnews/base/public/nsIMsgFolderCompactor.idl b/mailnews/base/public/nsIMsgFolderCompactor.idl index 04c12918f836..b69f0d4ee283 100644 --- a/mailnews/base/public/nsIMsgFolderCompactor.idl +++ b/mailnews/base/public/nsIMsgFolderCompactor.idl @@ -49,6 +49,6 @@ interface nsIMsgWindow; interface nsIMsgFolderCompactor : nsISupports { - void compact(in nsIMsgFolder aFolder, in nsIMsgWindow aMsgWindow); + void compact(in nsIMsgFolder aFolder, in boolean aOfflineStore, in nsIMsgWindow aMsgWindow); void compactAll(in nsISupportsArray aArrayOfFoldersToCompact, in nsIMsgWindow aMsgWindow, in boolean compactOfflineAlso, in nsISupportsArray aOfflineFolderArray); }; diff --git a/mailnews/base/src/nsMsgFolderCompactor.cpp b/mailnews/base/src/nsMsgFolderCompactor.cpp index 5e626d674228..92dfb49e0c89 100644 --- a/mailnews/base/src/nsMsgFolderCompactor.cpp +++ b/mailnews/base/src/nsMsgFolderCompactor.cpp @@ -55,6 +55,8 @@ #include "nsIPrompt.h" #include "nsIInterfaceRequestorUtils.h" #include "nsIMsgLocalMailFolder.h" +#include "nsIMsgImapMailFolder.h" + #include "nsMsgI18N.h" #include "prprf.h" #include "nsMsgLocalFolderHdrs.h" @@ -68,13 +70,13 @@ NS_IMPL_ISUPPORTS5(nsFolderCompactState, nsIMsgFolderCompactor, nsIRequestObserv nsFolderCompactState::nsFolderCompactState() { - m_baseMessageUri = nsnull; m_fileStream = nsnull; m_size = 0; m_curIndex = -1; m_status = NS_OK; m_compactAll = PR_FALSE; m_compactOfflineAlso = PR_FALSE; + m_compactingOfflineFolders = PR_FALSE; m_parsingFolder=PR_FALSE; m_folderIndex =0; m_startOfMsg = PR_TRUE; @@ -85,12 +87,6 @@ nsFolderCompactState::~nsFolderCompactState() { CloseOutputStream(); - if (m_baseMessageUri) - { - nsCRT::free(m_baseMessageUri); - m_baseMessageUri = nsnull; - } - if (NS_FAILED(m_status)) { CleanupTempFilesAfterError(); @@ -164,7 +160,12 @@ NS_IMETHODIMP nsFolderCompactState::CompactAll(nsISupportsArray *aArrayOfFolders nsresult rv = NS_OK; if (aArrayOfFoldersToCompact) m_folderArray =do_QueryInterface(aArrayOfFoldersToCompact, &rv); - + else if (aOfflineFolderArray) + { + m_folderArray = do_QueryInterface(aOfflineFolderArray, &rv); + m_compactingOfflineFolders = PR_TRUE; + aOfflineFolderArray = nsnull; + } if (NS_FAILED(rv) || !m_folderArray) return rv; @@ -178,14 +179,20 @@ NS_IMETHODIMP nsFolderCompactState::CompactAll(nsISupportsArray *aArrayOfFolders m_folderIndex, &rv); if (NS_SUCCEEDED(rv) && firstFolder) - Compact(firstFolder, aMsgWindow); //start with first folder from here. + Compact(firstFolder, m_compactingOfflineFolders, aMsgWindow); //start with first folder from here. return rv; } NS_IMETHODIMP -nsFolderCompactState::Compact(nsIMsgFolder *folder, nsIMsgWindow *aMsgWindow) +nsFolderCompactState::Compact(nsIMsgFolder *folder, PRBool aOfflineStore, nsIMsgWindow *aMsgWindow) { + if (!m_compactingOfflineFolders && !aOfflineStore) +{ + nsCOMPtr imapFolder = do_QueryInterface(folder); + if (imapFolder) + return folder->Compact(this, aMsgWindow); + } m_window = aMsgWindow; nsresult rv; nsCOMPtr db; @@ -275,9 +282,7 @@ nsFolderCompactState::Init(nsIMsgFolder *folder, const char *baseMsgUri, nsIMsgD nsresult rv; m_folder = folder; - m_baseMessageUri = nsCRT::strdup(baseMsgUri); - if (!m_baseMessageUri) - return NS_ERROR_OUT_OF_MEMORY; + m_baseMessageUri = baseMsgUri; pathSpec->GetFileSpec(&m_fileSpec); @@ -333,10 +338,12 @@ NS_IMETHODIMP nsFolderCompactState::OnStopRunningUrl(nsIURI *url, nsresult statu { m_parsingFolder=PR_FALSE; if (NS_SUCCEEDED(status)) - status=Compact(m_folder, m_window); + status=Compact(m_folder, m_compactingOfflineFolders, m_window); else if (m_compactAll) CompactNextFolder(); } + else if (m_compactAll) // this should be the imap case only + CompactNextFolder(); return NS_OK; } @@ -449,6 +456,7 @@ nsFolderCompactState::CompactNextFolder() { if (m_compactOfflineAlso) { + m_compactingOfflineFolders = PR_TRUE; nsCOMPtr folder = do_QueryElementAt(m_folderArray, m_folderIndex-1, &rv); if (NS_SUCCEEDED(rv) && folder) @@ -462,7 +470,7 @@ nsFolderCompactState::CompactNextFolder() m_folderIndex, &rv); if (NS_SUCCEEDED(rv) && folder) - rv = Compact(folder, m_window); + rv = Compact(folder, m_compactingOfflineFolders, m_window); return rv; } @@ -536,7 +544,7 @@ nsFolderCompactState::OnDataAvailable(nsIRequest *request, nsISupports *ctxt, { m_statusOffset = 0; m_messageUri.SetLength(0); // clear the previous message uri - if (NS_SUCCEEDED(BuildMessageURI(m_baseMessageUri, m_keyArray[m_curIndex], + if (NS_SUCCEEDED(BuildMessageURI(m_baseMessageUri.get(), m_keyArray[m_curIndex], m_messageUri))) { rv = GetMessage(getter_AddRefs(m_curSrcHdr)); @@ -674,7 +682,7 @@ nsOfflineStoreCompactState::OnStopRequest(nsIRequest *request, nsISupports *ctxt else { m_messageUri.SetLength(0); // clear the previous message uri - rv = BuildMessageURI(m_baseMessageUri, m_keyArray[m_curIndex], + rv = BuildMessageURI(m_baseMessageUri.get(), m_keyArray[m_curIndex], m_messageUri); if (NS_FAILED(rv)) goto done; rv = m_messageService->CopyMessage(m_messageUri.get(), this, PR_FALSE, nsnull, @@ -824,7 +832,7 @@ nsresult nsOfflineStoreCompactState::StartCompacting() AddRef(); // we own ourselves, until we're done, anyway. ShowCompactingStatusMsg(); m_messageUri.SetLength(0); // clear the previous message uri - rv = BuildMessageURI(m_baseMessageUri, + rv = BuildMessageURI(m_baseMessageUri.get(), m_keyArray[0], m_messageUri); if (NS_SUCCEEDED(rv)) diff --git a/mailnews/base/src/nsMsgFolderCompactor.h b/mailnews/base/src/nsMsgFolderCompactor.h index 2a5af9a12ae8..acd77e3ccdb3 100644 --- a/mailnews/base/src/nsMsgFolderCompactor.h +++ b/mailnews/base/src/nsMsgFolderCompactor.h @@ -80,7 +80,7 @@ protected: nsresult CompactNextFolder(); - char *m_baseMessageUri; // base message uri + nsCString m_baseMessageUri; // base message uri nsCString m_messageUri; // current message uri being copy nsCOMPtr m_folder; // current folder being compact nsCOMPtr m_db; // new database for the compact folder @@ -99,6 +99,7 @@ protected: PRUint32 m_folderIndex; // tells which folder to compact in case of compact all PRBool m_compactAll; //flag for compact all PRBool m_compactOfflineAlso; //whether to compact offline also + PRBool m_compactingOfflineFolders; // are we in the offline folder compact phase PRBool m_parsingFolder; //flag for parsing local folders; // these members are used to add missing status lines to compacted messages. PRBool m_needStatusLine; diff --git a/mailnews/base/src/nsMsgFolderDataSource.cpp b/mailnews/base/src/nsMsgFolderDataSource.cpp index 6f9d37a52d57..8a2f8659c7bf 100644 --- a/mailnews/base/src/nsMsgFolderDataSource.cpp +++ b/mailnews/base/src/nsMsgFolderDataSource.cpp @@ -787,7 +787,7 @@ nsMsgFolderDataSource::DoCommand(nsISupportsArray/**/* aSources, } else if ((aCommand == kNC_CompactAll)) { - rv = folder->CompactAll(nsnull, mWindow, nsnull, PR_FALSE, nsnull); + rv = folder->CompactAll(nsnull, mWindow, nsnull, PR_TRUE, nsnull); } else if ((aCommand == kNC_EmptyTrash)) { diff --git a/mailnews/base/util/nsMsgDBFolder.cpp b/mailnews/base/util/nsMsgDBFolder.cpp index 46b9f21cb9c1..dd535a9839de 100644 --- a/mailnews/base/util/nsMsgDBFolder.cpp +++ b/mailnews/base/util/nsMsgDBFolder.cpp @@ -1442,7 +1442,7 @@ nsresult nsMsgDBFolder::CompactOfflineStore(nsIMsgWindow *inWindow) nsresult rv; nsCOMPtr folderCompactor = do_CreateInstance(NS_MSGOFFLINESTORECOMPACTOR_CONTRACTID, &rv); if (NS_SUCCEEDED(rv) && folderCompactor) - rv = folderCompactor->Compact(this, inWindow); + rv = folderCompactor->Compact(this, PR_TRUE, inWindow); return rv; } @@ -1573,7 +1573,7 @@ nsMsgDBFolder::CompactAllOfflineStores(nsIMsgWindow *aWindow, nsISupportsArray * folderCompactor = do_CreateInstance(NS_MSGOFFLINESTORECOMPACTOR_CONTRACTID, &rv); if (NS_SUCCEEDED(rv) && folderCompactor) - rv = folderCompactor->CompactAll(aOfflineFolderArray, aWindow, PR_FALSE, nsnull); + rv = folderCompactor->CompactAll(nsnull, aWindow, PR_TRUE, aOfflineFolderArray); return rv; } diff --git a/mailnews/imap/src/nsImapMailFolder.cpp b/mailnews/imap/src/nsImapMailFolder.cpp index 4deb19c64587..00b13d19c16a 100644 --- a/mailnews/imap/src/nsImapMailFolder.cpp +++ b/mailnews/imap/src/nsImapMailFolder.cpp @@ -101,6 +101,7 @@ #include "nsNetUtil.h" #include "nsIMAPNamespace.h" #include "nsHashtable.h" +#include "nsIMsgFolderCompactor.h" #include "nsMsgMessageFlags.h" #include "nsIMimeHeaders.h" #include "nsIMsgMdnGenerator.h" @@ -1123,24 +1124,56 @@ NS_IMETHODIMP nsImapMailFolder::GetNoSelect(PRBool *aResult) NS_IMETHODIMP nsImapMailFolder::Compact(nsIUrlListener *aListener, nsIMsgWindow *aMsgWindow) { nsresult rv; - // compact offline part purely for testing purposes - if (WeAreOffline() && (mFlags & MSG_FOLDER_FLAG_OFFLINE)) - { - rv = CompactOfflineStore(aMsgWindow); - } - else - { + // compact offline store, if folder configured for offline use. + if (mFlags & MSG_FOLDER_FLAG_OFFLINE) + CompactOfflineStore(aMsgWindow); + nsCOMPtr imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv,rv); - rv = imapService->Expunge(m_eventQueue, this, aListener, nsnull); - } - return rv; + return imapService->Expunge(m_eventQueue, this, aListener, nsnull); } NS_IMETHODIMP nsImapMailFolder::CompactAll(nsIUrlListener *aListener, nsIMsgWindow *aMsgWindow, nsISupportsArray *aFolderArray, PRBool aCompactOfflineAlso, nsISupportsArray *aOfflineFolderArray) { - return Compact(aListener, aMsgWindow); //for now + NS_ASSERTION(!aOfflineFolderArray, "compacting automatically compacts offline stores"); + nsresult rv = NS_OK; + nsCOMPtr folderArray; + + if (!aFolderArray) + { + nsCOMPtr rootFolder; + nsCOMPtr allDescendents; + rv = GetRootFolder(getter_AddRefs(rootFolder)); + if (NS_SUCCEEDED(rv) && rootFolder) + { + NS_NewISupportsArray(getter_AddRefs(allDescendents)); + rootFolder->ListDescendents(allDescendents); + PRUint32 cnt =0; + rv = allDescendents->Count(&cnt); + NS_ENSURE_SUCCESS(rv,rv); + NS_NewISupportsArray(getter_AddRefs(folderArray)); + for (PRUint32 i=0; i< cnt;i++) + { + nsCOMPtr supports = getter_AddRefs(allDescendents->ElementAt(i)); + nsCOMPtr folder = do_QueryInterface(supports, &rv); + NS_ENSURE_SUCCESS(rv,rv); + rv = folderArray->AppendElement(supports); + + } + rv = folderArray->Count(&cnt); + NS_ENSURE_SUCCESS(rv,rv); + if (cnt == 0 ) + return NotifyCompactCompleted(); + } + } + nsCOMPtr folderCompactor = do_CreateInstance(NS_MSGLOCALFOLDERCOMPACTOR_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv) && folderCompactor) + if (aFolderArray) + rv = folderCompactor->CompactAll(aFolderArray, aMsgWindow, aCompactOfflineAlso, aOfflineFolderArray); + else if (folderArray) + rv = folderCompactor->CompactAll(folderArray, aMsgWindow, aCompactOfflineAlso, aOfflineFolderArray); + return rv; } NS_IMETHODIMP nsImapMailFolder::UpdateStatus(nsIUrlListener *aListener, nsIMsgWindow *aMsgWindow) diff --git a/mailnews/local/src/nsLocalMailFolder.cpp b/mailnews/local/src/nsLocalMailFolder.cpp index 977157d976d8..5ac24fbc4fb1 100644 --- a/mailnews/local/src/nsLocalMailFolder.cpp +++ b/mailnews/local/src/nsLocalMailFolder.cpp @@ -1046,7 +1046,7 @@ NS_IMETHODIMP nsMsgLocalMailFolder::Compact(nsIUrlListener *aListener, nsIMsgWin // check if we need to compact the folder if (expungedBytes > 0) - rv = folderCompactor->Compact(this, aMsgWindow); + rv = folderCompactor->Compact(this, PR_FALSE, aMsgWindow); else rv = NotifyCompactCompleted(); }