fix for wedged imap issue when undoing imap deletes after selecting trash, r=standard8, sr=neil, a=standard8, 444417
authorDavid Bienvenu <bienvenu@nventure.com>
Tue, 30 Sep 2008 09:51:32 -0700
changeset 477 c1bb787469fc01244d1f16b950d7dfae159728de
parent 476 aa07024355916e3ae36ab35239734f18bb33ab01
child 478 15aabb219a241e785cbfded316321343077dddc5
push idunknown
push userunknown
push dateunknown
reviewersstandard8, neil, standard8, 444417
bugs444417
fix for wedged imap issue when undoing imap deletes after selecting trash, r=standard8, sr=neil, a=standard8, 444417
mailnews/imap/src/nsImapUndoTxn.cpp
--- a/mailnews/imap/src/nsImapUndoTxn.cpp
+++ b/mailnews/imap/src/nsImapUndoTxn.cpp
@@ -177,60 +177,59 @@ nsImapMoveCopyMsgTxn::UndoTransaction(vo
       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)
-        CheckForToggleDelete(srcFolder, m_srcKeyArray[0], &deletedMsgs);
+      if (!m_srcMsgIdString.IsEmpty())
+      {
+        if (NS_SUCCEEDED(rv) && deleteModel == nsMsgImapDeleteModels::IMAPDelete)
+          CheckForToggleDelete(srcFolder, m_srcKeyArray[0], &deletedMsgs);
 
-      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 (NS_FAILED(rv)) 
-        return 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 (NS_FAILED(rv)) 
+          return rv;
 
-      if (deleteModel != nsMsgImapDeleteModels::IMAPDelete)
-        rv = imapService->GetHeaders(m_eventTarget, srcFolder,
-        srcListener, nsnull,
-                                     m_srcMsgIdString,
-        PR_TRUE); 
+        if (deleteModel != nsMsgImapDeleteModels::IMAPDelete)
+          rv = imapService->GetHeaders(m_eventTarget, srcFolder,
+                                srcListener, nsnull, m_srcMsgIdString, PR_TRUE);
+      }
     }
   }
   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);
     if (NS_FAILED(rv)) return 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(m_eventTarget, dstFolder,
       dstListener, nsnull);
     if (NS_FAILED(rv)) return rv;
-    rv = imapService->AddMessageFlags(m_eventTarget, dstFolder,
-      dstListener, nsnull,
-                                      m_dstMsgIdString,
-      kImapMsgDeletedFlag,
-      m_idsAreUids);
+    rv = imapService->AddMessageFlags(m_eventTarget, dstFolder, dstListener,
+                                      nsnull, m_dstMsgIdString, 
+                                      kImapMsgDeletedFlag, m_idsAreUids);
   }
   return rv;
 }
 
 NS_IMETHODIMP
 nsImapMoveCopyMsgTxn::RedoTransaction(void)
 {
   nsresult rv;
@@ -239,17 +238,17 @@ nsImapMoveCopyMsgTxn::RedoTransaction(vo
   
   if (m_isMove || !m_dstFolder)
   {
     if (m_srcIsPop3)
     {
       rv = RedoMailboxDelete();
       if (NS_FAILED(rv)) return rv;
     }
-    else
+    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); 
       if (NS_FAILED(rv)) 
         return rv;
@@ -262,69 +261,68 @@ nsImapMoveCopyMsgTxn::RedoTransaction(vo
       // 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 sire we are in the selected state; use lite select
-      // folder so we won't hit preformace hard
+      // 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);
       if (NS_FAILED(rv)) 
         return rv;
       if (deletedMsgs)
       {
-        rv = imapService->SubtractMessageFlags(m_eventTarget, srcFolder, 
+        rv = imapService->SubtractMessageFlags(m_eventTarget, srcFolder,
                                                 srcListener, nsnull,
-                                                m_srcMsgIdString, kImapMsgDeletedFlag,
+                                                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); 
     if (NS_FAILED(rv)) 
       return rv;
     // ** make sure we are in the selected state; use lite select
-    // folder so we won't hit preformace hard
+    // folder so we won't hit performance hard
     rv = imapService->LiteSelectFolder(m_eventTarget, dstFolder,
       dstListener, nsnull);
     if (NS_FAILED(rv)) 
       return rv;
     rv = imapService->SubtractMessageFlags(m_eventTarget, dstFolder,
-      dstListener, nsnull,
+                                           dstListener, nsnull, 
                                            m_dstMsgIdString,
-      kImapMsgDeletedFlag,
-      m_idsAreUids);
+                                           kImapMsgDeletedFlag,
+                                           m_idsAreUids);
     if (NS_FAILED(rv)) 
       return 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);
-  }
+      rv = imapService->GetHeaders(m_eventTarget, dstFolder, dstListener, 
+                                   nsnull, m_dstMsgIdString, PR_TRUE);
+    }
   }
   return rv;
 }
 
 nsresult
 nsImapMoveCopyMsgTxn::SetCopyResponseUid(const char* aMsgIdString)
 {
   if (!aMsgIdString) return NS_ERROR_NULL_POINTER;
@@ -604,16 +602,23 @@ NS_IMETHODIMP nsImapOfflineTxn::RedoTran
         if (m_opType == nsIMsgOfflineImapOperation::kMsgCopy)
         {
           op->SetOperation(nsIMsgOfflineImapOperation::kMsgMoved);
           op->AddMessageCopyOperation(folderURI.get()); // offline copy
         }
         dstFolder->SummaryChanged();
       }
     }
+    else if (!WeAreOffline())
+    {
+      // couldn't find offline op - it must have been played back already
+      // so we should redo the transaction online.
+      return nsImapMoveCopyMsgTxn::RedoTransaction();
+    }
+
     break;
   case nsIMsgOfflineImapOperation::kAddedHeader:
     {
       nsCOMPtr <nsIMsgDBHdr> restoreHdr;
       nsMsgKey msgKey;
       m_header->GetMessageKey(&msgKey);
       nsCOMPtr<nsIMsgFolder> dstFolder = do_QueryReferent(m_dstFolder, &rv);
       rv = srcFolder->GetDBFolderInfoAndDB(getter_AddRefs(folderInfo), getter_AddRefs(destDB));