NS_IMETHODIMP nsFolderCompactState::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult status) { nsCOMPtr<nsIMsgDBHdr> msgHdr; nsCOMPtr<nsIMsgDBHdr> newMsgHdr; if (NS_FAILED(status)) { m_status = status; // set the m_status to status so the destructor can remove the // temp folder and database m_folder->NotifyCompactCompleted(); ReleaseFolderLock(); } else { EndCopy(nsnull, status); if (m_curIndex >= m_size) { msgHdr = nsnull; newMsgHdr = nsnull; // no more to copy finish it up FinishCompact(); } else { // in case we're not getting an error, we still need to pretend we did get an error, // because the compact did not successfully complete. m_folder->NotifyCompactCompleted(); CleanupTempFilesAfterError(); ReleaseFolderLock(); } } Release(); // kill self return status; }
nsresult nsPop3Sink::AbortMailDelivery(nsIPop3Protocol *protocol) { CheckPartialMessages(protocol); // ### PS TODO - discard any new message? if (m_outFileStream) { m_outFileStream->Close(); m_outFileStream = 0; } if (m_downloadingToTempFile && m_tmpDownloadFile) m_tmpDownloadFile->Remove(false); /* tell the parser to mark the db valid *after* closing the mailbox. we have truncated the inbox, so berkeley mailbox and msf file are in sync*/ if (m_newMailParser) m_newMailParser->UpdateDBFolderInfo(); MOZ_LOG(POP3LOGMODULE, mozilla::LogLevel::Debug, (POP3LOG("Calling ReleaseFolderLock from AbortMailDelivery"))); nsresult rv = ReleaseFolderLock(); NS_ASSERTION(NS_SUCCEEDED(rv),"folder lock not released successfully"); #ifdef DEBUG printf("Abort mail message delivery.\n"); #endif nsCOMPtr<nsIPop3Service> pop3Service(do_GetService(NS_POP3SERVICE_CONTRACTID1, &rv)); NS_ENSURE_SUCCESS(rv, rv); pop3Service->NotifyDownloadCompleted(m_folder, 0); return NS_OK; }
nsresult nsOfflineStoreCompactState::StartCompacting() { nsresult rv = NS_OK; if (m_size > 0 && m_curIndex == 0) { AddRef(); // we own ourselves, until we're done, anyway. ShowCompactingStatusMsg(); bool done = false; rv = CopyNextMessage(done); if (!done) return rv; } ReleaseFolderLock(); FinishCompact(); return rv; }
nsPop3Sink::~nsPop3Sink() { MOZ_LOG(POP3LOGMODULE, mozilla::LogLevel::Debug, (POP3LOG("Calling ReleaseFolderLock from ~nsPop3Sink"))); ReleaseFolderLock(); }
nsresult nsPop3Sink::EndMailDelivery(nsIPop3Protocol *protocol) { CheckPartialMessages(protocol); if (m_newMailParser) { if (m_outFileStream) m_outFileStream->Flush(); // try this. m_newMailParser->OnStopRequest(nullptr, nullptr, NS_OK); m_newMailParser->EndMsgDownload(); } if (m_outFileStream) { m_outFileStream->Close(); m_outFileStream = 0; } if (m_downloadingToTempFile) m_tmpDownloadFile->Remove(false); // tell the parser to mark the db valid *after* closing the mailbox. if (m_newMailParser) m_newMailParser->UpdateDBFolderInfo(); MOZ_LOG(POP3LOGMODULE, mozilla::LogLevel::Debug, (POP3LOG("Calling ReleaseFolderLock from EndMailDelivery"))); nsresult rv = ReleaseFolderLock(); NS_ASSERTION(NS_SUCCEEDED(rv),"folder lock not released successfully"); bool filtersRun; m_folder->CallFilterPlugins(nullptr, &filtersRun); // ??? do we need msgWindow? int32_t numNewMessagesInFolder; // if filters have marked msgs read or deleted, the num new messages count // will go negative by the number of messages marked read or deleted, // so if we add that number to the number of msgs downloaded, that will give // us the number of actual new messages. m_folder->GetNumNewMessages(false, &numNewMessagesInFolder); m_numNewMessages -= (m_numNewMessagesInFolder - numNewMessagesInFolder); m_folder->SetNumNewMessages(m_numNewMessages); // we'll adjust this for spam later if (!filtersRun && m_numNewMessages > 0) { nsCOMPtr <nsIMsgIncomingServer> server; m_folder->GetServer(getter_AddRefs(server)); if (server) { server->SetPerformingBiff(true); m_folder->SetBiffState(m_biffState); server->SetPerformingBiff(false); } } // note that size on disk has possibly changed. nsCOMPtr<nsIMsgLocalMailFolder> localFolder = do_QueryInterface(m_folder); if (localFolder) (void) localFolder->RefreshSizeOnDisk(); nsCOMPtr<nsIMsgIncomingServer> server = do_QueryInterface(m_popServer); if (server) { nsCOMPtr <nsIMsgFilterList> filterList; rv = server->GetFilterList(nullptr, getter_AddRefs(filterList)); NS_ENSURE_SUCCESS(rv, rv); if (filterList) (void) filterList->FlushLogIfNecessary(); } // fix for bug #161999 // we should update the summary totals for the folder (inbox) // in case it's not the open folder m_folder->UpdateSummaryTotals(true); // check if the folder open in this window is not the current folder, and if it has new // message, in which case we need to try to run the filter plugin. if (m_newMailParser) { nsCOMPtr <nsIMsgWindow> msgWindow; m_newMailParser->GetMsgWindow(getter_AddRefs(msgWindow)); // this breaks down if it's biff downloading new mail because // there's no msgWindow... if (msgWindow) { nsCOMPtr <nsIMsgFolder> openFolder; (void) msgWindow->GetOpenFolder(getter_AddRefs(openFolder)); if (openFolder && openFolder != m_folder) { // only call filter plugins if folder is a local folder, because only // local folders get messages filtered into them synchronously by pop3. nsCOMPtr<nsIMsgLocalMailFolder> localFolder = do_QueryInterface(openFolder); if (localFolder) { bool hasNew, isLocked; (void) openFolder->GetHasNewMessages(&hasNew); if (hasNew) { // if the open folder is locked, we shouldn't run the spam filters // on it because someone is using the folder. see 218433. // Ideally, the filter plugin code would try to grab the folder lock // and hold onto it until done, but that's more difficult and I think // this will actually fix the problem. openFolder->GetLocked(&isLocked); if(!isLocked) openFolder->CallFilterPlugins(nullptr, &filtersRun); } } } } } #ifdef DEBUG printf("End mail message delivery.\n"); #endif nsCOMPtr<nsIPop3Service> pop3Service(do_GetService(NS_POP3SERVICE_CONTRACTID1, &rv)); NS_ENSURE_SUCCESS(rv, rv); pop3Service->NotifyDownloadCompleted(m_folder, m_numNewMessages); return NS_OK; }
NS_IMETHODIMP nsOfflineStoreCompactState::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult status) { nsresult rv = status; nsCOMPtr<nsIURI> uri; nsCOMPtr<nsIMsgDBHdr> msgHdr; nsCOMPtr<nsIMsgDBHdr> newMsgHdr; nsCOMPtr <nsIMsgStatusFeedback> statusFeedback; bool done = false; // The NS_MSG_ERROR_MSG_NOT_OFFLINE error should allow us to continue, so we // check for it specifically and don't terminate the compaction. if (NS_FAILED(rv) && rv != NS_MSG_ERROR_MSG_NOT_OFFLINE) goto done; uri = do_QueryInterface(ctxt, &rv); if (NS_FAILED(rv)) goto done; rv = GetMessage(getter_AddRefs(msgHdr)); if (NS_FAILED(rv)) goto done; if (msgHdr) { if (NS_SUCCEEDED(status)) { msgHdr->SetMessageOffset(m_startOfNewMsg); char storeToken[100]; PR_snprintf(storeToken, sizeof(storeToken), "%lld", m_startOfNewMsg); msgHdr->SetStringProperty("storeToken", storeToken); msgHdr->SetOfflineMessageSize(m_offlineMsgSize); } else { PRUint32 resultFlags; msgHdr->AndFlags(~nsMsgMessageFlags::Offline, &resultFlags); } } if (m_window) { m_window->GetStatusFeedback(getter_AddRefs(statusFeedback)); if (statusFeedback) statusFeedback->ShowProgress (100 * m_curIndex / m_size); } // advance to next message m_curIndex++; rv = CopyNextMessage(done); if (done) { m_db->Commit(nsMsgDBCommitType::kCompressCommit); msgHdr = nsnull; newMsgHdr = nsnull; // no more to copy finish it up ReleaseFolderLock(); FinishCompact(); Release(); // kill self } done: if (NS_FAILED(rv)) { m_status = rv; // set the status to rv so the destructor can remove the // temp folder and database ReleaseFolderLock(); Release(); // kill self return rv; } return rv; }
nsresult nsFolderCompactState::FinishCompact() { if (!m_folder) return NS_ERROR_NOT_INITIALIZED; // All okay time to finish up the compact process nsCOMPtr<nsILocalFile> path; nsCOMPtr<nsIDBFolderInfo> folderInfo; // get leaf name and database name of the folder nsresult rv = m_folder->GetFilePath(getter_AddRefs(path)); nsCOMPtr <nsILocalFile> folderPath = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr <nsILocalFile> summaryFile; folderPath->InitWithFile(path); // need to make sure we put the .msf file in the same directory // as the original mailbox, so resolve symlinks. folderPath->SetFollowLinks(true); GetSummaryFileLocation(folderPath, getter_AddRefs(summaryFile)); nsCString leafName; summaryFile->GetNativeLeafName(leafName); nsCAutoString dbName(leafName); path->GetNativeLeafName(leafName); // close down the temp file stream; preparing for deleting the old folder // and its database; then rename the temp folder and database m_fileStream->Flush(); m_fileStream->Close(); m_fileStream = nsnull; // make sure the new database is valid. // Close it so we can rename the .msf file. if (m_db) { m_db->ForceClosed(); m_db = nsnull; } nsCOMPtr <nsILocalFile> newSummaryFile; GetSummaryFileLocation(m_file, getter_AddRefs(newSummaryFile)); nsCOMPtr <nsIDBFolderInfo> transferInfo; m_folder->GetDBTransferInfo(getter_AddRefs(transferInfo)); // close down database of the original folder m_folder->ForceDBClosed(); nsCOMPtr<nsIFile> cloneFile; PRInt64 fileSize; m_file->Clone(getter_AddRefs(cloneFile)); cloneFile->GetFileSize(&fileSize); bool tempFileRightSize = (fileSize == m_totalMsgSize); NS_ASSERTION(tempFileRightSize, "temp file not of expected size in compact"); bool folderRenameSucceeded = false; bool msfRenameSucceeded = false; if (tempFileRightSize) { bool summaryFileExists; // remove the old folder and database rv = summaryFile->Remove(false); summaryFile->Exists(&summaryFileExists); if (NS_SUCCEEDED(rv) && !summaryFileExists) { bool folderPathExists; rv = folderPath->Remove(false); folderPath->Exists(&folderPathExists); if (NS_SUCCEEDED(rv) && !folderPathExists) { // rename the copied folder and database to be the original folder and // database rv = m_file->MoveToNative((nsIFile *) nsnull, leafName); NS_ASSERTION(NS_SUCCEEDED(rv), "error renaming compacted folder"); if (NS_SUCCEEDED(rv)) { folderRenameSucceeded = true; rv = newSummaryFile->MoveToNative((nsIFile *) nsnull, dbName); NS_ASSERTION(NS_SUCCEEDED(rv), "error renaming compacted folder's db"); msfRenameSucceeded = NS_SUCCEEDED(rv); } } } NS_ASSERTION(msfRenameSucceeded && folderRenameSucceeded, "rename failed in compact"); } if (!folderRenameSucceeded) m_file->Remove(false); if (!msfRenameSucceeded) newSummaryFile->Remove(false); rv = ReleaseFolderLock(); NS_ASSERTION(NS_SUCCEEDED(rv),"folder lock not released successfully"); if (msfRenameSucceeded && folderRenameSucceeded) { nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = msgDBService->OpenFolderDB(m_folder, true, getter_AddRefs(m_db)); m_db->SetSummaryValid(true); m_folder->SetDBTransferInfo(transferInfo); nsCOMPtr<nsIDBFolderInfo> dbFolderInfo; m_db->GetDBFolderInfo(getter_AddRefs(dbFolderInfo)); // since we're transferring info from the old db, we need to reset the expunged bytes, // and set the summary valid again. if(dbFolderInfo) dbFolderInfo->SetExpungedBytes(0); } if (m_db) m_db->Close(true); m_db = nsnull; // Notify that compaction of the folder is completed. nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID)); if (notifier) notifier->NotifyItemEvent(m_folder, NS_LITERAL_CSTRING("FolderCompactFinish"), nsnull); m_folder->NotifyCompactCompleted(); if (m_compactAll) rv = CompactNextFolder(); else CompactCompleted(NS_OK); return rv; }
nsresult nsFolderCompactState::FinishCompact() { NS_ENSURE_TRUE(m_folder, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_TRUE(m_file, NS_ERROR_NOT_INITIALIZED); // All okay time to finish up the compact process nsCOMPtr<nsIFile> path; nsCOMPtr<nsIDBFolderInfo> folderInfo; // get leaf name and database name of the folder nsresult rv = m_folder->GetFilePath(getter_AddRefs(path)); nsCOMPtr <nsIFile> folderPath = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = folderPath->InitWithFile(path); NS_ENSURE_SUCCESS(rv, rv); // need to make sure we put the .msf file in the same directory // as the original mailbox, so resolve symlinks. folderPath->SetFollowLinks(true); nsCOMPtr <nsIFile> oldSummaryFile; rv = GetSummaryFileLocation(folderPath, getter_AddRefs(oldSummaryFile)); NS_ENSURE_SUCCESS(rv, rv); nsAutoCString dbName; oldSummaryFile->GetNativeLeafName(dbName); nsAutoCString folderName; path->GetNativeLeafName(folderName); // close down the temp file stream; preparing for deleting the old folder // and its database; then rename the temp folder and database if (m_fileStream) { m_fileStream->Flush(); m_fileStream->Close(); m_fileStream = nullptr; } // make sure the new database is valid. // Close it so we can rename the .msf file. if (m_db) { m_db->ForceClosed(); m_db = nullptr; } nsCOMPtr <nsIFile> newSummaryFile; rv = GetSummaryFileLocation(m_file, getter_AddRefs(newSummaryFile)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr <nsIDBFolderInfo> transferInfo; m_folder->GetDBTransferInfo(getter_AddRefs(transferInfo)); // close down database of the original folder m_folder->ForceDBClosed(); nsCOMPtr<nsIFile> cloneFile; int64_t fileSize; rv = m_file->Clone(getter_AddRefs(cloneFile)); if (NS_SUCCEEDED(rv)) rv = cloneFile->GetFileSize(&fileSize); bool tempFileRightSize = (fileSize == m_totalMsgSize); NS_WARN_IF_FALSE(tempFileRightSize, "temp file not of expected size in compact"); bool folderRenameSucceeded = false; bool msfRenameSucceeded = false; if (NS_SUCCEEDED(rv) && tempFileRightSize) { // First we're going to try and move the old summary file out the way. // We don't delete it yet, as we want to keep the files in sync. nsCOMPtr<nsIFile> tempSummaryFile; rv = oldSummaryFile->Clone(getter_AddRefs(tempSummaryFile)); if (NS_SUCCEEDED(rv)) rv = tempSummaryFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600); nsAutoCString tempSummaryFileName; if (NS_SUCCEEDED(rv)) rv = tempSummaryFile->GetNativeLeafName(tempSummaryFileName); if (NS_SUCCEEDED(rv)) rv = oldSummaryFile->MoveToNative((nsIFile*) nullptr, tempSummaryFileName); NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "error moving compacted folder's db out of the way"); if (NS_SUCCEEDED(rv)) { // Now we've successfully moved the summary file out the way, try moving // the newly compacted message file over the old one. rv = m_file->MoveToNative((nsIFile *) nullptr, folderName); folderRenameSucceeded = NS_SUCCEEDED(rv); NS_WARN_IF_FALSE(folderRenameSucceeded, "error renaming compacted folder"); if (folderRenameSucceeded) { // That worked, so land the new summary file in the right place. nsCOMPtr<nsIFile> renamedCompactedSummaryFile; newSummaryFile->Clone(getter_AddRefs(renamedCompactedSummaryFile)); if (renamedCompactedSummaryFile) { rv = renamedCompactedSummaryFile->MoveToNative((nsIFile *) nullptr, dbName); msfRenameSucceeded = NS_SUCCEEDED(rv); } NS_WARN_IF_FALSE(msfRenameSucceeded, "error renaming compacted folder's db"); } if (!msfRenameSucceeded) { // Do our best to put the summary file back to where it was rv = tempSummaryFile->MoveToNative((nsIFile*) nullptr, dbName); if (NS_SUCCEEDED(rv)) tempSummaryFile = nullptr; // flagging that a renamed db no longer exists else NS_WARNING("error restoring uncompacted folder's db"); } } // We don't want any temporarily renamed summary file to lie around if (tempSummaryFile) tempSummaryFile->Remove(false); } NS_WARN_IF_FALSE(msfRenameSucceeded, "compact failed"); rv = ReleaseFolderLock(); NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),"folder lock not released successfully"); // Cleanup of nstmp-named compacted files if failure if (!folderRenameSucceeded) { // remove the abandoned compacted version with the wrong name m_file->Remove(false); } if (!msfRenameSucceeded) { // remove the abandoned compacted summary file newSummaryFile->Remove(false); } if (msfRenameSucceeded) { // Transfer local db information from transferInfo nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = msgDBService->OpenFolderDB(m_folder, true, getter_AddRefs(m_db)); NS_ENSURE_TRUE(m_db, NS_FAILED(rv) ? rv : NS_ERROR_FAILURE); m_db->SetSummaryValid(true); m_folder->SetDBTransferInfo(transferInfo); // since we're transferring info from the old db, we need to reset the expunged bytes nsCOMPtr<nsIDBFolderInfo> dbFolderInfo; m_db->GetDBFolderInfo(getter_AddRefs(dbFolderInfo)); if(dbFolderInfo) dbFolderInfo->SetExpungedBytes(0); } if (m_db) m_db->Close(true); m_db = nullptr; // Notify that compaction of the folder is completed. nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID)); if (notifier) notifier->NotifyItemEvent(m_folder, NS_LITERAL_CSTRING("FolderCompactFinish"), nullptr); m_folder->NotifyCompactCompleted(); if (m_compactAll) rv = CompactNextFolder(); else CompactCompleted(NS_OK); return rv; }
nsPop3Sink::~nsPop3Sink() { PR_LOG(POP3LOGMODULE, PR_LOG_MAX, ("Calling ReleaseFolderLock from ~nsPop3Sink")); ReleaseFolderLock(); }