From 8f643700769994e4d43bc624370007eeeac8280c Mon Sep 17 00:00:00 2001 From: "bienvenu%netscape.com" Date: Sat, 2 Sep 2000 14:42:14 +0000 Subject: [PATCH] fix 50722 problems renaming open imap folder r=mscott git-svn-id: svn://10.0.0.236/trunk@78020 18797224-902f-48f8-a5cc-f745e15eee43 --- .../imap/public/nsIImapIncomingServer.idl | 1 + .../imap/public/nsIMsgImapMailFolder.idl | 2 + .../imap/src/nsImapIncomingServer.cpp | 40 ++++++ .../mailnews/imap/src/nsImapMailFolder.cpp | 121 +++++++++++------- mozilla/mailnews/imap/src/nsImapMailFolder.h | 1 + mozilla/mailnews/imap/src/nsImapProtocol.cpp | 8 +- 6 files changed, 126 insertions(+), 47 deletions(-) diff --git a/mozilla/mailnews/imap/public/nsIImapIncomingServer.idl b/mozilla/mailnews/imap/public/nsIImapIncomingServer.idl index bd5033e389d..afd7beaa6cd 100644 --- a/mozilla/mailnews/imap/public/nsIImapIncomingServer.idl +++ b/mozilla/mailnews/imap/public/nsIImapIncomingServer.idl @@ -71,6 +71,7 @@ interface nsIImapIncomingServer : nsISupports { void ResetNamespaceReferences(); void PseudoInterruptMsgLoad(in nsIImapUrl aImapUrl, out boolean interrupted); void ResetConnection(in string folderName); + void CloseConnectionForFolder(in nsIMsgFolder aMsgFolder); void CreatePRUnicharStringFromUTF7(in string aSourceString, out wstring aUnicodeStr); void reDiscoverAllFolders(); attribute boolean doingLsub; diff --git a/mozilla/mailnews/imap/public/nsIMsgImapMailFolder.idl b/mozilla/mailnews/imap/public/nsIMsgImapMailFolder.idl index e2ec3e29ac4..712321f9af0 100644 --- a/mozilla/mailnews/imap/public/nsIMsgImapMailFolder.idl +++ b/mozilla/mailnews/imap/public/nsIMsgImapMailFolder.idl @@ -24,6 +24,7 @@ #include "nsIMsgFolder.idl" interface nsIMsgWindow; +interface nsIImapIncomingServer; [scriptable, uuid(FBFEBE79-C1DD-11d2-8A40-0060B0FC04D2)] interface nsIMsgImapMailFolder : nsISupports { @@ -33,6 +34,7 @@ interface nsIMsgImapMailFolder : nsISupports { void RenameLocal(in string newname); void PrepareToRename(); void PerformExpand(in nsIMsgWindow aMsgWindow); + void RecursiveCloseActiveConnections(in nsIImapIncomingServer aImapServer); attribute boolean verifiedAsOnlineFolder; attribute boolean explicitlyVerify; diff --git a/mozilla/mailnews/imap/src/nsImapIncomingServer.cpp b/mozilla/mailnews/imap/src/nsImapIncomingServer.cpp index 75c9203504d..7c8b3bede07 100644 --- a/mozilla/mailnews/imap/src/nsImapIncomingServer.cpp +++ b/mozilla/mailnews/imap/src/nsImapIncomingServer.cpp @@ -737,6 +737,46 @@ nsImapIncomingServer::CreateProtocolInstance(nsIEventQueue *aEventQueue, return rv; } +NS_IMETHODIMP nsImapIncomingServer::CloseConnectionForFolder(nsIMsgFolder *aMsgFolder) +{ + nsresult rv = NS_OK; + nsCOMPtr connection; + nsCOMPtr aSupport; + PRBool isBusy = PR_FALSE, isInbox = PR_FALSE; + PRUint32 cnt = 0; + nsXPIDLCString inFolderName; + nsXPIDLCString connectionFolderName; + nsCOMPtr imapFolder = do_QueryInterface(aMsgFolder); + + if (!imapFolder) + return NS_ERROR_NULL_POINTER; + + rv = m_connectionCache->Count(&cnt); + if (NS_FAILED(rv)) return rv; + + imapFolder->GetOnlineName(getter_Copies(inFolderName)); + PR_CEnterMonitor(this); + + for (PRUint32 i=0; i < cnt; i++) + { + aSupport = getter_AddRefs(m_connectionCache->ElementAt(i)); + connection = do_QueryInterface(aSupport); + if (connection) + { + rv = connection->GetSelectedMailboxName(getter_Copies(connectionFolderName)); + if (PL_strcmp(connectionFolderName,inFolderName) == 0) + { + rv = connection->IsBusy(&isBusy, &isInbox); + if (!isBusy) + rv = connection->TellThreadToDie(PR_TRUE); + break; // found it, end of the loop + } + } + } + + PR_CExitMonitor(this); + return rv; +} NS_IMETHODIMP nsImapIncomingServer::ResetConnection(const char* folderName) { diff --git a/mozilla/mailnews/imap/src/nsImapMailFolder.cpp b/mozilla/mailnews/imap/src/nsImapMailFolder.cpp index ab2ed85b954..3973f0dbecd 100644 --- a/mozilla/mailnews/imap/src/nsImapMailFolder.cpp +++ b/mozilla/mailnews/imap/src/nsImapMailFolder.cpp @@ -945,6 +945,12 @@ NS_IMETHODIMP nsImapMailFolder::Delete () NS_IMETHODIMP nsImapMailFolder::Rename (const PRUnichar *newName) { nsresult rv = NS_ERROR_FAILURE; + nsCOMPtr incomingImapServer; + + GetImapIncomingServer(getter_AddRefs(incomingImapServer)); + if (incomingImapServer) + RecursiveCloseActiveConnections(incomingImapServer); + NS_WITH_SERVICE (nsIImapService, imapService, kCImapService, &rv); if (NS_SUCCEEDED(rv)) rv = imapService->RenameLeaf(m_eventQueue, this, newName, this, @@ -952,6 +958,31 @@ NS_IMETHODIMP nsImapMailFolder::Rename (const PRUnichar *newName) return rv; } +NS_IMETHODIMP nsImapMailFolder::RecursiveCloseActiveConnections(nsIImapIncomingServer *incomingImapServer) +{ + NS_ENSURE_ARG(incomingImapServer); + incomingImapServer->CloseConnectionForFolder(this); + PRUint32 cnt = 0, i; + if (mSubFolders) + { + nsCOMPtr aSupport; + nsCOMPtr folder; + mSubFolders->Count(&cnt); + if (cnt > 0) + { + for (i = 0; i < cnt; i++) + { + aSupport = getter_AddRefs(mSubFolders->ElementAt(i)); + folder = do_QueryInterface(aSupport); + if (folder) + folder->RecursiveCloseActiveConnections(incomingImapServer); + } + } + } + return NS_OK; +} + +// this is called *after* we've done the rename on the server. NS_IMETHODIMP nsImapMailFolder::PrepareToRename() { PRUint32 cnt = 0, i; @@ -1123,6 +1154,24 @@ nsresult nsImapMailFolder::GetServerKey(char **serverKey) return rv; } +nsresult nsImapMailFolder::GetImapIncomingServer(nsIImapIncomingServer **aImapIncomingServer) +{ + NS_ENSURE_ARG(aImapIncomingServer); + + *aImapIncomingServer = nsnull; + + nsCOMPtr server; + + if (NS_SUCCEEDED(GetServer(getter_AddRefs(server))) && server) + { + nsCOMPtr incomingServer = do_QueryInterface(server); + *aImapIncomingServer = incomingServer; + NS_IF_ADDREF(*aImapIncomingServer); + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} + NS_IMETHODIMP nsImapMailFolder::UserNeedsToAuthenticateForFolder(PRBool displayOnly, PRBool @@ -1447,27 +1496,24 @@ NS_IMETHODIMP nsImapMailFolder::DeleteMessages(nsISupportsArray *messages, nsIMsgWindow *msgWindow, PRBool deleteStorage, PRBool isMove) { - nsresult rv = NS_ERROR_FAILURE; - // *** jt - assuming delete is move to the trash folder for now - nsCOMPtr aEnumerator; - nsCOMPtr res; - nsCAutoString uri; - PRBool deleteImmediatelyNoTrash = PR_FALSE; - nsCAutoString messageIds; - nsMsgKeyArray srcKeyArray; + nsresult rv = NS_ERROR_FAILURE; + // *** jt - assuming delete is move to the trash folder for now + nsCOMPtr aEnumerator; + nsCOMPtr res; + nsCAutoString uri; + PRBool deleteImmediatelyNoTrash = PR_FALSE; + nsCAutoString messageIds; + nsMsgKeyArray srcKeyArray; - nsMsgImapDeleteModel deleteModel = nsMsgImapDeleteModels::MoveToTrash; + nsMsgImapDeleteModel deleteModel = nsMsgImapDeleteModels::MoveToTrash; nsCOMPtr imapServer; - nsCOMPtr server; - rv = GetFlag(MSG_FOLDER_FLAG_TRASH, &deleteImmediatelyNoTrash); + rv = GetImapIncomingServer(getter_AddRefs(imapServer)); - if (NS_SUCCEEDED(GetServer(getter_AddRefs(server))) && server) + if (NS_SUCCEEDED(rv) && imapServer) { - imapServer = do_QueryInterface(server); - if (imapServer) - imapServer->GetDeleteModel(&deleteModel); + imapServer->GetDeleteModel(&deleteModel); if (deleteModel != nsMsgImapDeleteModels::MoveToTrash || deleteStorage) deleteImmediatelyNoTrash = PR_TRUE; } @@ -1617,19 +1663,14 @@ nsImapMailFolder::DeleteSubFolders(nsISupportsArray* folders, nsIMsgWindow *msgW if (canHaveSubFoldersOfTrash) // UW server doesn't set NOINFERIORS - check dual use pref { nsCOMPtr imapServer; - nsCOMPtr server; + rv = GetImapIncomingServer(getter_AddRefs(imapServer)); - rv = GetServer(getter_AddRefs(server)); - if (server) + if (NS_SUCCEEDED(rv) && imapServer) { - imapServer = do_QueryInterface(server, &rv); - if (NS_SUCCEEDED(rv) && imapServer) - { - PRBool serverSupportsDualUseFolders; - imapServer->GetDualUseFolders(&serverSupportsDualUseFolders); - if (!serverSupportsDualUseFolders) - canHaveSubFoldersOfTrash = PR_FALSE; - } + PRBool serverSupportsDualUseFolders; + imapServer->GetDualUseFolders(&serverSupportsDualUseFolders); + if (!serverSupportsDualUseFolders) + canHaveSubFoldersOfTrash = PR_FALSE; } } if (!canHaveSubFoldersOfTrash) @@ -3089,23 +3130,18 @@ PRBool nsImapMailFolder::ShowDeletedMessages() if (!showDeleted) { nsCOMPtr imapServer; - nsCOMPtr server; + nsresult rv = GetImapIncomingServer(getter_AddRefs(imapServer)); - nsresult rv = GetServer(getter_AddRefs(server)); - if (server) + if (NS_SUCCEEDED(rv) && imapServer) { - imapServer = do_QueryInterface(server, &rv); - if (NS_SUCCEEDED(rv) && imapServer) + PRBool isAOLServer = PR_FALSE; + imapServer->GetIsAOLServer(&isAOLServer); + if (isAOLServer) { - PRBool isAOLServer = PR_FALSE; - imapServer->GetIsAOLServer(&isAOLServer); - if (isAOLServer) - { - nsXPIDLString folderName; - GetName(getter_Copies(folderName)); - if (!nsCRT::strncasecmp(folderName, "Trash", 5)) - showDeleted = PR_TRUE; - } + nsXPIDLString folderName; + GetName(getter_Copies(folderName)); + if (!nsCRT::strncasecmp(folderName, "Trash", 5)) + showDeleted = PR_TRUE; } } } @@ -4377,11 +4413,8 @@ NS_IMETHODIMP nsImapMailFolder::PerformExpand(nsIMsgWindow *aMsgWindow) nsresult rv; PRBool usingSubscription = PR_FALSE; nsCOMPtr imapServer; - nsCOMPtr server; + rv = GetImapIncomingServer(getter_AddRefs(imapServer)); - rv = GetServer(getter_AddRefs(server)); - if (NS_FAILED(rv) || !server) return NS_ERROR_FAILURE; - imapServer = do_QueryInterface(server, &rv); if (NS_FAILED(rv) || !imapServer) return NS_ERROR_FAILURE; rv = imapServer->GetUsingSubscription(&usingSubscription); if (NS_SUCCEEDED(rv) && !usingSubscription) diff --git a/mozilla/mailnews/imap/src/nsImapMailFolder.h b/mozilla/mailnews/imap/src/nsImapMailFolder.h index 023c2115738..6524fd3652c 100644 --- a/mozilla/mailnews/imap/src/nsImapMailFolder.h +++ b/mozilla/mailnews/imap/src/nsImapMailFolder.h @@ -284,6 +284,7 @@ protected: nsresult GetTrashFolder(nsIMsgFolder **pTrashFolder); PRBool TrashOrDescendentOfTrash(nsIMsgFolder* folder); nsresult GetServerKey(char **serverKey); + nsresult GetImapIncomingServer(nsIImapIncomingServer **aImapIncomingServer); nsresult DisplayStatusMsg(nsIImapUrl *aImapUrl, const PRUnichar *msg); diff --git a/mozilla/mailnews/imap/src/nsImapProtocol.cpp b/mozilla/mailnews/imap/src/nsImapProtocol.cpp index cccca36a9d7..6384cdccc7e 100644 --- a/mozilla/mailnews/imap/src/nsImapProtocol.cpp +++ b/mozilla/mailnews/imap/src/nsImapProtocol.cpp @@ -778,6 +778,8 @@ nsImapProtocol::TellThreadToDie(PRBool isSaveToClose) // **** jt - This routine should only be called by imap service. nsAutoCMonitor(this); + m_urlInProgress = PR_TRUE; // let's say it's busy so no one tries to use + // this about to die connection. PRBool closeNeeded = GetServerStateParser().GetIMAPstate() == nsImapServerResponseParser::kFolderSelected && isSaveToClose; nsCString command; @@ -1399,7 +1401,7 @@ NS_IMETHODIMP nsImapProtocol::IsBusy(PRBool *aIsConnectionBusy, } #define IS_SUBSCRIPTION_RELATED_ACTION(action) (action == nsIImapUrl::nsImapSubscribe\ -|| action == nsIImapUrl::nsImapUnsubscribe || action == nsIImapUrl::nsImapDiscoverAllBoxesUrl) +|| action == nsIImapUrl::nsImapUnsubscribe || action == nsIImapUrl::nsImapDiscoverAllBoxesUrl || action == nsIImapUrl::nsImapListFolder) // canRunUrl means the connection is not busy, and is in the selcted state @@ -1460,7 +1462,7 @@ NS_IMETHODIMP nsImapProtocol::CanHandleUrl(nsIImapUrl * aImapUrl, aImapUrl->GetRequiredImapState(&imapState); // OK, this is a bit of a hack - we're going to pretend that - // a delete folder url requires a selected state connection on + // a delete or rename folder url requires a selected state connection on // the folder to be deleted. This isn't technically true, // but we would much rather use that connection for several reasons, // one is that some UW servers require us to use that connection @@ -1469,7 +1471,7 @@ NS_IMETHODIMP nsImapProtocol::CanHandleUrl(nsIImapUrl * aImapUrl, // If we don't find a connection in that selected state, // we'll fall back to the first free connection. PRBool isSelectedStateUrl = imapState == nsIImapUrl::nsImapSelectedState - || actionForProposedUrl == nsIImapUrl::nsImapDeleteFolder; + || actionForProposedUrl == nsIImapUrl::nsImapDeleteFolder || actionForProposedUrl == nsIImapUrl::nsImapRenameFolder; nsCOMPtr msgUrl = do_QueryInterface(aImapUrl); nsCOMPtr server;