NS_IMETHODIMP nsImapMoveCopyMsgTxn::UndoTransaction(void) { nsresult rv; nsCOMPtr<nsIImapService> imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); bool finishInOnStopRunningUrl = false; if (m_isMove || !m_dstFolder) { if (m_srcIsPop3) { rv = UndoMailboxDelete(); NS_ENSURE_SUCCESS(rv, rv); } else { nsCOMPtr<nsIMsgFolder> srcFolder = do_QueryReferent(m_srcFolder, &rv); if (NS_FAILED(rv) || !srcFolder) return rv; nsCOMPtr<nsIUrlListener> srcListener = do_QueryInterface(srcFolder, &rv); if (NS_FAILED(rv)) return rv; m_onStopListener = do_GetWeakReference(srcListener); // ** make sure we are in the selected state; use lite select // folder so we won't hit performance hard rv = imapService->LiteSelectFolder(srcFolder, srcListener, nullptr, nullptr); if (NS_FAILED(rv)) return rv; bool deletedMsgs = true; //default is true unless imapDelete model nsMsgImapDeleteModel deleteModel; rv = GetImapDeleteModel(srcFolder, &deleteModel); // protect against a bogus undo txn without any source keys // see bug #179856 for details NS_ASSERTION(!m_srcKeyArray.IsEmpty(), "no source keys"); if (m_srcKeyArray.IsEmpty()) return NS_ERROR_UNEXPECTED; if (!m_srcMsgIdString.IsEmpty()) { if (NS_SUCCEEDED(rv) && deleteModel == nsMsgImapDeleteModels::IMAPDelete) CheckForToggleDelete(srcFolder, m_srcKeyArray[0], &deletedMsgs); if (deletedMsgs) rv = imapService->SubtractMessageFlags(srcFolder, this, nullptr, m_srcMsgIdString, kImapMsgDeletedFlag, m_idsAreUids); else rv = imapService->AddMessageFlags(srcFolder, srcListener, nullptr, m_srcMsgIdString, kImapMsgDeletedFlag, m_idsAreUids); if (NS_FAILED(rv)) return rv; finishInOnStopRunningUrl = true; if (deleteModel != nsMsgImapDeleteModels::IMAPDelete) rv = imapService->GetHeaders(srcFolder, srcListener, nullptr, m_srcMsgIdString, true); } } } if (!finishInOnStopRunningUrl && !m_dstMsgIdString.IsEmpty()) { nsCOMPtr<nsIMsgFolder> dstFolder = do_QueryReferent(m_dstFolder, &rv); if (NS_FAILED(rv) || !dstFolder) return rv; nsCOMPtr<nsIUrlListener> dstListener; dstListener = do_QueryInterface(dstFolder, &rv); NS_ENSURE_SUCCESS(rv, rv); // ** make sure we are in the selected state; use lite select folder // so we won't potentially download a bunch of headers. rv = imapService->LiteSelectFolder(dstFolder, dstListener, nullptr, nullptr); NS_ENSURE_SUCCESS(rv, rv); rv = imapService->AddMessageFlags(dstFolder, dstListener, nullptr, m_dstMsgIdString, kImapMsgDeletedFlag, m_idsAreUids); } return rv; }
NS_IMETHODIMP nsLocalMoveCopyMsgTxn::RedoTransaction() { nsresult rv; nsCOMPtr<nsIMsgDatabase> srcDB; nsCOMPtr<nsIMsgDatabase> dstDB; nsCOMPtr<nsIMsgFolder> srcFolder = do_QueryReferent(m_srcFolder, &rv); NS_ENSURE_SUCCESS(rv,rv); nsCOMPtr<nsIMsgFolder> dstFolder = do_QueryReferent(m_dstFolder, &rv); NS_ENSURE_SUCCESS(rv,rv); rv = srcFolder->GetMsgDatabase(getter_AddRefs(srcDB)); if(NS_FAILED(rv)) return rv; rv = dstFolder->GetMsgDatabase(getter_AddRefs(dstDB)); if (NS_FAILED(rv)) return rv; uint32_t count = m_srcKeyArray.Length(); uint32_t i; nsCOMPtr<nsIMsgDBHdr> oldHdr; nsCOMPtr<nsIMsgDBHdr> newHdr; nsCOMPtr<nsIMutableArray> srcMessages = do_CreateInstance(NS_ARRAY_CONTRACTID); nsCOMPtr <nsISupports> msgSupports; for (i=0; i<count; i++) { rv = srcDB->GetMsgHdrForKey(m_srcKeyArray[i], getter_AddRefs(oldHdr)); NS_ASSERTION(oldHdr, "fatal ... cannot get old msg header\n"); if (NS_SUCCEEDED(rv) && oldHdr) { msgSupports =do_QueryInterface(oldHdr); srcMessages->AppendElement(msgSupports, false); if (m_canUndelete) { rv = dstDB->CopyHdrFromExistingHdr(m_dstKeyArray[i], oldHdr, true, getter_AddRefs(newHdr)); NS_ASSERTION(newHdr, "fatal ... cannot get new msg header\n"); if (NS_SUCCEEDED(rv) && newHdr) { if (i < m_dstSizeArray.Length()) rv = newHdr->SetMessageSize(m_dstSizeArray[i]); dstDB->UndoDelete(newHdr); } } } } dstDB->SetSummaryValid(true); if (m_isMove) { if (m_srcIsImap4) { // protect against a bogus undo txn without any source keys // see bug #179856 for details NS_ASSERTION(!m_srcKeyArray.IsEmpty(), "no source keys"); if (m_srcKeyArray.IsEmpty()) return NS_ERROR_UNEXPECTED; bool deleteFlag = false; //message is un-deleted- we are trying to redo CheckForToggleDelete(srcFolder, m_srcKeyArray[0], &deleteFlag); // there could have been a toggle rv = UndoImapDeleteFlag(srcFolder, m_srcKeyArray, deleteFlag); } else if (m_canUndelete) { nsCOMPtr <nsIMsgLocalMailFolder> localFolder = do_QueryInterface(srcFolder); if (localFolder) localFolder->MarkMsgsOnPop3Server(srcMessages, POP3_DELETE /*deleteMsgs*/); rv = srcDB->DeleteMessages(m_srcKeyArray.Length(), m_srcKeyArray.Elements(), nullptr); srcDB->SetSummaryValid(true); } else { nsCOMPtr<nsIMsgDBHdr> srcHdr; m_numHdrsCopied = 0; m_dstKeyArray.Clear(); for (i = 0; i < count; i++) { srcDB->GetMsgHdrForKey(m_srcKeyArray[i], getter_AddRefs(srcHdr)); NS_ASSERTION(srcHdr, "fatal ... cannot get old msg header\n"); if (srcHdr) { nsCString messageId; srcHdr->GetMessageId(getter_Copies(messageId)); m_copiedMsgIds.AppendElement(messageId); } } dstFolder->AddFolderListener(this); m_undoing = false; return dstFolder->CopyMessages(srcFolder, srcMessages, true, nullptr, nullptr, false, false); } } return rv; }
NS_IMETHODIMP nsImapMoveCopyMsgTxn::RedoTransaction(void) { nsresult rv; nsCOMPtr<nsIImapService> imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); if (m_isMove || !m_dstFolder) { if (m_srcIsPop3) { rv = RedoMailboxDelete(); if (NS_FAILED(rv)) return rv; } else if (!m_srcMsgIdString.IsEmpty()) { nsCOMPtr<nsIMsgFolder> srcFolder = do_QueryReferent(m_srcFolder, &rv); if (NS_FAILED(rv) || !srcFolder) return rv; nsCOMPtr<nsIUrlListener> srcListener = do_QueryInterface(srcFolder, &rv); NS_ENSURE_SUCCESS(rv, rv); PRBool deletedMsgs = PR_FALSE; //default will be false unless imapDeleteModel; nsMsgImapDeleteModel deleteModel; rv = GetImapDeleteModel(srcFolder, &deleteModel); // protect against a bogus undo txn without any source keys // see bug #179856 for details NS_ASSERTION(!m_srcKeyArray.IsEmpty(), "no source keys"); if (m_srcKeyArray.IsEmpty()) return NS_ERROR_UNEXPECTED; if (NS_SUCCEEDED(rv) && deleteModel == nsMsgImapDeleteModels::IMAPDelete) rv = CheckForToggleDelete(srcFolder, m_srcKeyArray[0], &deletedMsgs); // Make sure we are in the selected state; use lite select // folder so performance won't suffer. rv = imapService->LiteSelectFolder(m_eventTarget, srcFolder, srcListener, nsnull, nsnull); NS_ENSURE_SUCCESS(rv, rv); if (deletedMsgs) { rv = imapService->SubtractMessageFlags(m_eventTarget, srcFolder, srcListener, nsnull, m_srcMsgIdString, kImapMsgDeletedFlag, m_idsAreUids); } else { rv = imapService->AddMessageFlags(m_eventTarget, srcFolder, srcListener, nsnull, m_srcMsgIdString, kImapMsgDeletedFlag, m_idsAreUids); } } } if (!m_dstMsgIdString.IsEmpty()) { nsCOMPtr<nsIMsgFolder> dstFolder = do_QueryReferent(m_dstFolder, &rv); if (NS_FAILED(rv) || !dstFolder) return rv; nsCOMPtr<nsIUrlListener> dstListener; dstListener = do_QueryInterface(dstFolder, &rv); NS_ENSURE_SUCCESS(rv, rv); // ** make sure we are in the selected state; use lite select // folder so we won't hit performance hard rv = imapService->LiteSelectFolder(m_eventTarget, dstFolder, dstListener, nsnull, nsnull); NS_ENSURE_SUCCESS(rv, rv); rv = imapService->SubtractMessageFlags(m_eventTarget, dstFolder, dstListener, nsnull, m_dstMsgIdString, kImapMsgDeletedFlag, m_idsAreUids); NS_ENSURE_SUCCESS(rv, rv); nsMsgImapDeleteModel deleteModel; rv = GetImapDeleteModel(dstFolder, &deleteModel); if (NS_FAILED(rv) || deleteModel == nsMsgImapDeleteModels::MoveToTrash) { rv = imapService->GetHeaders(m_eventTarget, dstFolder, dstListener, nsnull, m_dstMsgIdString, PR_TRUE); } } return rv; }
nsresult nsLocalMoveCopyMsgTxn::UndoTransactionInternal() { nsresult rv = NS_ERROR_FAILURE; if (mUndoFolderListener) { nsCOMPtr<nsIMsgMailSession> mailSession = do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv,rv); rv = mailSession->RemoveFolderListener(mUndoFolderListener); NS_ENSURE_SUCCESS(rv,rv); NS_RELEASE(mUndoFolderListener); mUndoFolderListener = nullptr; } nsCOMPtr<nsIMsgDatabase> srcDB; nsCOMPtr<nsIMsgDatabase> dstDB; nsCOMPtr<nsIMsgFolder> srcFolder = do_QueryReferent(m_srcFolder, &rv); NS_ENSURE_SUCCESS(rv,rv); nsCOMPtr<nsIMsgFolder> dstFolder = do_QueryReferent(m_dstFolder, &rv); NS_ENSURE_SUCCESS(rv,rv); rv = srcFolder->GetMsgDatabase(getter_AddRefs(srcDB)); if(NS_FAILED(rv)) return rv; rv = dstFolder->GetMsgDatabase(getter_AddRefs(dstDB)); if (NS_FAILED(rv)) return rv; uint32_t count = m_srcKeyArray.Length(); uint32_t i; nsCOMPtr<nsIMsgDBHdr> oldHdr; nsCOMPtr<nsIMsgDBHdr> newHdr; // protect against a bogus undo txn without any source keys // see bug #179856 for details NS_ASSERTION(count, "no source keys"); if (!count) return NS_ERROR_UNEXPECTED; if (m_isMove) { if (m_srcIsImap4) { bool deleteFlag = true; //message has been deleted -we are trying to undo it CheckForToggleDelete(srcFolder, m_srcKeyArray[0], &deleteFlag); //there could have been a toggle. rv = UndoImapDeleteFlag(srcFolder, m_srcKeyArray, deleteFlag); } else if (m_canUndelete) { nsCOMPtr<nsIMutableArray> srcMessages = do_CreateInstance(NS_ARRAY_CONTRACTID); nsCOMPtr<nsIMutableArray> dstMessages = do_CreateInstance(NS_ARRAY_CONTRACTID); srcDB->StartBatch(); for (i = 0; i < count; i++) { rv = dstDB->GetMsgHdrForKey(m_dstKeyArray[i], getter_AddRefs(oldHdr)); NS_ASSERTION(oldHdr, "fatal ... cannot get old msg header\n"); if (NS_SUCCEEDED(rv) && oldHdr) { rv = srcDB->CopyHdrFromExistingHdr(m_srcKeyArray[i], oldHdr, true, getter_AddRefs(newHdr)); NS_ASSERTION(newHdr, "fatal ... cannot create new msg header\n"); if (NS_SUCCEEDED(rv) && newHdr) { newHdr->SetStatusOffset(m_srcStatusOffsetArray[i]); srcDB->UndoDelete(newHdr); srcMessages->AppendElement(newHdr, false); // (we want to keep these two lists in sync) dstMessages->AppendElement(oldHdr, false); } } } srcDB->EndBatch(); nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID)); if (notifier) { // Remember that we're actually moving things back from the destination // to the source! notifier->NotifyMsgsMoveCopyCompleted(true, dstMessages, srcFolder, srcMessages); } nsCOMPtr <nsIMsgLocalMailFolder> localFolder = do_QueryInterface(srcFolder); if (localFolder) localFolder->MarkMsgsOnPop3Server(srcMessages, POP3_NONE /*deleteMsgs*/); } else // undoing a move means moving the messages back. { nsCOMPtr<nsIMutableArray> dstMessages = do_CreateInstance(NS_ARRAY_CONTRACTID); nsCOMPtr<nsIMsgDBHdr> dstHdr; m_numHdrsCopied = 0; m_srcKeyArray.Clear(); for (i = 0; i < count; i++) { dstDB->GetMsgHdrForKey(m_dstKeyArray[i], getter_AddRefs(dstHdr)); NS_ASSERTION(dstHdr, "fatal ... cannot get old msg header\n"); if (dstHdr) { nsCString messageId; dstHdr->GetMessageId(getter_Copies(messageId)); dstMessages->AppendElement(dstHdr, false); m_copiedMsgIds.AppendElement(messageId); } } srcFolder->AddFolderListener(this); m_undoing = true; return srcFolder->CopyMessages(dstFolder, dstMessages, true, nullptr, nullptr, false, false); } srcDB->SetSummaryValid(true); } dstDB->DeleteMessages(m_dstKeyArray.Length(), m_dstKeyArray.Elements(), nullptr); dstDB->SetSummaryValid(true); return rv; }
nsresult nsLocalMoveCopyMsgTxn::UndoTransactionInternal() { nsresult rv = NS_ERROR_FAILURE; if (mUndoFolderListener) { nsCOMPtr<nsIMsgMailSession> mailSession = do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv,rv); rv = mailSession->RemoveFolderListener(mUndoFolderListener); NS_ENSURE_SUCCESS(rv,rv); NS_RELEASE(mUndoFolderListener); mUndoFolderListener = nsnull; } nsCOMPtr<nsIMsgDatabase> srcDB; nsCOMPtr<nsIMsgDatabase> dstDB; nsCOMPtr<nsIMsgFolder> srcFolder = do_QueryReferent(m_srcFolder, &rv); NS_ENSURE_SUCCESS(rv,rv); nsCOMPtr<nsIMsgFolder> dstFolder = do_QueryReferent(m_dstFolder, &rv); NS_ENSURE_SUCCESS(rv,rv); rv = srcFolder->GetMsgDatabase(nsnull, getter_AddRefs(srcDB)); if(NS_FAILED(rv)) return rv; rv = dstFolder->GetMsgDatabase(nsnull, getter_AddRefs(dstDB)); if (NS_FAILED(rv)) return rv; PRUint32 count = m_srcKeyArray.Length(); PRUint32 i; nsCOMPtr<nsIMsgDBHdr> oldHdr; nsCOMPtr<nsIMsgDBHdr> newHdr; // protect against a bogus undo txn without any source keys // see bug #179856 for details NS_ASSERTION(count, "no source keys"); if (!count) return NS_ERROR_UNEXPECTED; if (m_isMove) { if (m_srcIsImap4) { PRBool deleteFlag = PR_TRUE; //message has been deleted -we are trying to undo it CheckForToggleDelete(srcFolder, m_srcKeyArray[0], &deleteFlag); //there could have been a toggle. rv = UndoImapDeleteFlag(srcFolder, m_srcKeyArray, deleteFlag); } else { nsCOMPtr<nsIMutableArray> srcMessages = do_CreateInstance(NS_ARRAY_CONTRACTID); for (i=0; i<count; i++) { rv = dstDB->GetMsgHdrForKey(m_dstKeyArray[i], getter_AddRefs(oldHdr)); NS_ASSERTION(oldHdr, "fatal ... cannot get old msg header\n"); if (NS_SUCCEEDED(rv) && oldHdr) { rv = srcDB->CopyHdrFromExistingHdr(m_srcKeyArray[i], oldHdr, PR_TRUE, getter_AddRefs(newHdr)); NS_ASSERTION(newHdr, "fatal ... cannot create new msg header\n"); if (NS_SUCCEEDED(rv) && newHdr) { newHdr->SetStatusOffset(m_srcStatusOffsetArray[i]); srcDB->UndoDelete(newHdr); srcMessages->AppendElement(newHdr, PR_FALSE); } } } nsCOMPtr <nsIMsgLocalMailFolder> localFolder = do_QueryInterface(srcFolder); if (localFolder) localFolder->MarkMsgsOnPop3Server(srcMessages, POP3_NONE /*deleteMsgs*/); } srcDB->SetSummaryValid(PR_TRUE); } dstDB->DeleteMessages(&m_dstKeyArray, nsnull); dstDB->SetSummaryValid(PR_TRUE); return rv; }