From 3d5f029e03cac48f0fbee4c407f63c31c2c0ae2a Mon Sep 17 00:00:00 2001 From: "ere%atp.fi" Date: Wed, 27 Nov 2002 12:20:37 +0000 Subject: [PATCH] Bug 24064: Need ability to specify Trash folder r=Henry.Jia sr=bienvenu --- .../imap/public/nsIImapIncomingServer.idl | 2 + mailnews/imap/src/nsImapIncomingServer.cpp | 74 ++++++++++++++++++- mailnews/imap/src/nsImapMailFolder.cpp | 37 ++++++++-- mailnews/imap/src/nsImapMailFolder.h | 2 + mailnews/imap/src/nsImapProtocol.cpp | 35 ++++++--- mailnews/imap/src/nsImapProtocol.h | 2 + 6 files changed, 133 insertions(+), 19 deletions(-) diff --git a/mailnews/imap/public/nsIImapIncomingServer.idl b/mailnews/imap/public/nsIImapIncomingServer.idl index 4a047f77eb2..24ee95a69dc 100644 --- a/mailnews/imap/public/nsIImapIncomingServer.idl +++ b/mailnews/imap/public/nsIImapIncomingServer.idl @@ -81,6 +81,8 @@ interface nsIImapIncomingServer : nsISupports { attribute boolean aOLMailboxView; attribute boolean storeReadMailInPFC; attribute boolean storeSentMailInPFC; + attribute wstring trashFolderName; + boolean getIsPFC(in string folderName); nsIMsgFolder getPFC(in boolean createIfMissing); attribute boolean downloadBodiesOnGetNewMail; diff --git a/mailnews/imap/src/nsImapIncomingServer.cpp b/mailnews/imap/src/nsImapIncomingServer.cpp index fdc54fcc05d..d46e61a5493 100644 --- a/mailnews/imap/src/nsImapIncomingServer.cpp +++ b/mailnews/imap/src/nsImapIncomingServer.cpp @@ -94,6 +94,9 @@ #include "nsITimer.h" #include "nsMsgUtils.h" +#define PREF_TRASH_FOLDER_NAME "trash_folder_name" +#define DEFAULT_TRASH_FOLDER_NAME "Trash" + static NS_DEFINE_CID(kCImapHostSessionList, NS_IIMAPHOSTSESSIONLIST_CID); static NS_DEFINE_CID(kImapProtocolCID, NS_IMAPPROTOCOL_CID); static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); @@ -1584,7 +1587,6 @@ nsresult nsImapIncomingServer::GetFolder(const char* name, nsIMsgFolder** pFolde return rv; } - NS_IMETHODIMP nsImapIncomingServer::OnlineFolderDelete(const char *aFolderName) { return NS_OK; @@ -1724,7 +1726,37 @@ NS_IMETHODIMP nsImapIncomingServer::DiscoveryDone() if (NS_FAILED(rv)) return rv; nsCOMPtr rootMsgFolder = do_QueryInterface(rootFolder, &rv); if (rootMsgFolder) + { rootMsgFolder->SetPrefFlag(); + } + + // Verify there is only one trash folder. Another might be present if + // the trash name has been changed. + PRUint32 numFolders; + rv = rootMsgFolder->GetFoldersWithFlag(MSG_FOLDER_FLAG_TRASH, 0, &numFolders, NULL); + + if (NS_SUCCEEDED(rv) && numFolders > 1) + { + nsXPIDLString trashName; + if (NS_SUCCEEDED(GetTrashFolderName(getter_Copies(trashName)))) + { + nsIMsgFolder *trashFolders[2]; + if (NS_SUCCEEDED(rootMsgFolder->GetFoldersWithFlag(MSG_FOLDER_FLAG_TRASH, 2, + &numFolders, trashFolders))) + { + for (int i = 0; i < numFolders; i++) + { + nsXPIDLString folderName; + if (NS_SUCCEEDED(trashFolders[i]->GetName(getter_Copies(folderName))) && + !folderName.Equals(trashName)) + { + trashFolders[i]->ClearFlag(MSG_FOLDER_FLAG_TRASH); + } + NS_RELEASE(trashFolders[i]); + } + } + } + } } PRInt32 numUnverifiedFolders; @@ -3733,3 +3765,43 @@ nsImapIncomingServer::GetUriWithNamespacePrefixIfNecessary(PRInt32 namespaceType } return rv; } + +NS_IMETHODIMP nsImapIncomingServer::GetTrashFolderName(PRUnichar **retval) +{ + nsresult rv = GetUnicharValue(PREF_TRASH_FOLDER_NAME, retval); + if (NS_FAILED(rv)) + return rv; + + if (!*retval || !**retval) + { + // if GetUnicharValue() above returned allocated empty string, we must free it first + // before allocating space and assigning the default value + if (*retval) + nsMemory::Free(*retval); + *retval = ToNewUnicode(NS_LITERAL_STRING(DEFAULT_TRASH_FOLDER_NAME)); + } + return NS_OK; +} + +NS_IMETHODIMP nsImapIncomingServer::SetTrashFolderName(const PRUnichar *chvalue) +{ + // clear trash flag from the old pref + nsXPIDLString oldTrashName; + nsresult rv = GetTrashFolderName(getter_Copies(oldTrashName)); + if (NS_SUCCEEDED(rv)) + { + char *oldTrashNameUtf7 = CreateUtf7ConvertedStringFromUnicode(oldTrashName); + if (oldTrashNameUtf7) + { + nsCOMPtr oldFolder; + rv = GetFolder(oldTrashNameUtf7, getter_AddRefs(oldFolder)); + if (NS_SUCCEEDED(rv) && oldFolder) + { + oldFolder->ClearFlag(MSG_FOLDER_FLAG_TRASH); + } + PR_Free(oldTrashNameUtf7); + } + } + + return SetUnicharValue(PREF_TRASH_FOLDER_NAME, chvalue); +} diff --git a/mailnews/imap/src/nsImapMailFolder.cpp b/mailnews/imap/src/nsImapMailFolder.cpp index ea1a095f814..53db8a81078 100644 --- a/mailnews/imap/src/nsImapMailFolder.cpp +++ b/mailnews/imap/src/nsImapMailFolder.cpp @@ -375,9 +375,13 @@ NS_IMETHODIMP nsImapMailFolder::AddSubfolderWithPath(nsAutoString *name, nsIFile name->Equals(NS_LITERAL_STRING("Inbox"), nsCaseInsensitiveStringComparator())) flags |= MSG_FOLDER_FLAG_INBOX; - else if((isServer || isParentInbox) && name->Equals(NS_LITERAL_STRING("Trash"), - nsCaseInsensitiveStringComparator())) - flags |= MSG_FOLDER_FLAG_TRASH; + else if(isServer || isParentInbox) + { + nsAutoString trashName; + GetTrashFolderName(trashName); + if (name->Equals(trashName)) + flags |= MSG_FOLDER_FLAG_TRASH; + } #if 0 else if(name->EqualsIgnoreCase(NS_LITERAL_STRING("Sent"))) folder->SetFlag(MSG_FOLDER_FLAG_SENTMAIL); @@ -750,7 +754,9 @@ NS_IMETHODIMP nsImapMailFolder::CreateSubfolder(const PRUnichar* folderName, nsI if (!folderName) return rv; - if ( nsDependentString(folderName).Equals(NS_LITERAL_STRING("Trash"),nsCaseInsensitiveStringComparator()) ) // Trash , a special folder + nsAutoString trashName; + GetTrashFolderName(trashName); + if ( nsDependentString(folderName).Equals(trashName) ) // Trash , a special folder { ThrowAlertMsg("folderExists", msgWindow); return NS_MSG_FOLDER_EXISTS; @@ -4183,10 +4189,8 @@ nsresult nsImapMailFolder::GetTrashFolder(nsIMsgFolder **pTrashFolder) { PRUint32 numFolders; rv = rootFolder->GetFoldersWithFlag(MSG_FOLDER_FLAG_TRASH, 1, &numFolders, pTrashFolder); - if (numFolders != 1) - rv = NS_ERROR_FAILURE; - if (*pTrashFolder) - NS_ADDREF(*pTrashFolder); + if (numFolders != 1) + rv = NS_ERROR_FAILURE; } return rv; } @@ -7205,3 +7209,20 @@ nsImapMailFolder::GetShouldDownloadAllHeaders(PRBool *aResult) } +void nsImapMailFolder::GetTrashFolderName(nsAString &aFolderName) +{ + nsCOMPtr server; + nsCOMPtr imapServer; + + if (NS_SUCCEEDED(GetServer(getter_AddRefs(server))) && server) + imapServer = do_QueryInterface(server); + + if (imapServer) + { + nsXPIDLString trashFolderName; + if (NS_SUCCEEDED(imapServer->GetTrashFolderName(getter_Copies(trashFolderName)))) + { + aFolderName = trashFolderName; + } + } +} diff --git a/mailnews/imap/src/nsImapMailFolder.h b/mailnews/imap/src/nsImapMailFolder.h index 7e04f4b2d46..03b0513a936 100644 --- a/mailnews/imap/src/nsImapMailFolder.h +++ b/mailnews/imap/src/nsImapMailFolder.h @@ -436,6 +436,8 @@ protected: nsresult CopyOfflineMsgBody(nsIMsgFolder *srcFolder, nsIMsgDBHdr *destHdr, nsIMsgDBHdr *origHdr); + void GetTrashFolderName(nsAString &aFolderName); + PRBool m_initialized; PRBool m_haveDiscoveredAllFolders; PRBool m_haveReadNameFromDB; diff --git a/mailnews/imap/src/nsImapProtocol.cpp b/mailnews/imap/src/nsImapProtocol.cpp index 721b4de292b..ca934f8d04a 100644 --- a/mailnews/imap/src/nsImapProtocol.cpp +++ b/mailnews/imap/src/nsImapProtocol.cpp @@ -108,8 +108,6 @@ PRLogModuleInfo *IMAP; #define ONE_SECOND ((PRUint32)1000) // one second -const char *kImapTrashFolderName = "Trash"; // **** needs to be localized **** - static NS_DEFINE_CID(kIStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID); static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID); static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); @@ -4136,7 +4134,6 @@ nsImapProtocol::GetSubscribingNow() void nsImapProtocol::DiscoverMailboxSpec(nsImapMailboxSpec * adoptedBoxSpec) { - // IMAP_LoadTrashFolderName(); **** needs to work on localization issues nsIMAPNamespace *ns = nsnull; NS_ASSERTION (m_hostSessionList, "fatal null host session list"); @@ -4164,7 +4161,7 @@ nsImapProtocol::DiscoverMailboxSpec(nsImapMailboxSpec * adoptedBoxSpec) // if not using the Trash model !onlineTrashFolderExists && PL_strstr(adoptedBoxSpec->allocatedPathName, - kImapTrashFolderName)) + GetTrashFolderName())) { PRBool trashExists = PR_FALSE; nsCString trashMatch(CreatePossibleTrashName(nsPrefix)); @@ -6483,17 +6480,35 @@ void nsImapProtocol::RenameMailbox(const char *existingName, char * nsImapProtocol::CreatePossibleTrashName(const char *prefix) { - // mscott we used to have a localized global string for the trash name... - // I haven't don't localization stuff yet so I'm going to do a bad thing and just - // use a string literal....(only temporary!!!!! =))... - -// IMAP_LoadTrashFolderName(); nsCString returnTrash(prefix); - returnTrash += "Trash"; + returnTrash += GetTrashFolderName(); return ToNewCString(returnTrash); } +const char * nsImapProtocol::GetTrashFolderName() +{ + if (m_trashFolderName.IsEmpty()) + { + nsCOMPtr server = do_QueryReferent(m_server); + if (server) + { + nsXPIDLString trashFolderName; + if (NS_SUCCEEDED(server->GetTrashFolderName(getter_Copies(trashFolderName)))) + { + char *trashFolderNameUtf7 = CreateUtf7ConvertedStringFromUnicode(trashFolderName); + if (trashFolderNameUtf7) + { + m_trashFolderName.Assign(trashFolderNameUtf7); + PR_Free(trashFolderNameUtf7); + } + } + } + } + + return m_trashFolderName.get(); +} + void nsImapProtocol::Lsub(const char *mailboxPattern, PRBool addDirectoryIfNecessary) { ProgressEventFunctionUsingId (IMAP_STATUS_LOOKING_FOR_MAILBOX); diff --git a/mailnews/imap/src/nsImapProtocol.h b/mailnews/imap/src/nsImapProtocol.h index 656cc85b79e..a257cb54cdc 100644 --- a/mailnews/imap/src/nsImapProtocol.h +++ b/mailnews/imap/src/nsImapProtocol.h @@ -387,6 +387,7 @@ private: PRUint32 m_allocatedSize; // allocated size PRUint32 m_totalDataSize; // total data size PRUint32 m_curReadIndex; // current read index + nsCAutoString m_trashFolderName; // Ouput stream for writing commands to the socket nsCOMPtr m_channel; @@ -568,6 +569,7 @@ private: PRBool MailboxIsNoSelectMailbox(const char *mailboxName); char * CreatePossibleTrashName(const char *prefix); + const char * GetTrashFolderName(); PRBool FolderNeedsACLInitialized(const char *folderName); void DiscoverMailboxList(); void DiscoverAllAndSubscribedBoxes();