mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 06:35:42 +00:00
1923 lines
46 KiB
C++
1923 lines
46 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
#include "msgCore.h" // precompiled header...
|
|
|
|
#include "nsMsgFolder.h"
|
|
#include "nsMsgFolderFlags.h"
|
|
#include "prprf.h"
|
|
#include "nsMsgKeyArray.h"
|
|
#include "nsMsgDatabase.h"
|
|
#include "nsIDBFolderInfo.h"
|
|
#include "nsISupportsArray.h"
|
|
#include "nsIPref.h"
|
|
#include "nsIRDFService.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "nsRDFCID.h"
|
|
#include "nsXPIDLString.h"
|
|
|
|
// stuff for temporary root folder hack
|
|
#include "nsIMsgMailSession.h"
|
|
#include "nsIMsgIncomingServer.h"
|
|
#include "nsIPop3IncomingServer.h"
|
|
#include "nsINntpIncomingServer.h"
|
|
|
|
static NS_DEFINE_CID(kMsgMailSessionCID, NS_MSGMAILSESSION_CID);
|
|
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
|
|
|
|
|
// we need this because of an egcs 1.0 (and possibly gcc) compiler bug
|
|
// that doesn't allow you to call ::nsISupports::GetIID() inside of a class
|
|
// that multiply inherits from nsISupports
|
|
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
|
|
|
nsMsgFolder::nsMsgFolder(void)
|
|
: nsRDFResource(), mFlags(0),
|
|
mNumUnreadMessages(0), mNumTotalMessages(0),
|
|
mListeners(nsnull),
|
|
mCsid(0),
|
|
mDepth(0),
|
|
mPrefFlags(0)
|
|
{
|
|
// NS_INIT_REFCNT(); done by superclass
|
|
|
|
#ifdef HAVE_MASTER
|
|
mMaster = NULL;
|
|
#endif
|
|
|
|
mSemaphoreHolder = NULL;
|
|
|
|
#ifdef HAVE_DB
|
|
mLastMessageLoaded = nsMsgKey_None;
|
|
#endif
|
|
mNumPendingUnreadMessages = 0;
|
|
mNumPendingTotalMessages = 0;
|
|
NS_NewISupportsArray(&mSubFolders);
|
|
|
|
mIsCachable = TRUE;
|
|
|
|
//The rdf:mailnewsfolders datasource is going to be a listener to all nsIMsgFolders, so add
|
|
//it as a listener
|
|
nsresult rv;
|
|
NS_WITH_SERVICE(nsIRDFService, rdfService, kRDFServiceCID, &rv);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsIRDFDataSource* datasource = nsnull;
|
|
|
|
if(NS_SUCCEEDED(rv = rdfService->GetDataSource("rdf:mailnewsfolders", &datasource)))
|
|
{
|
|
nsIFolderListener *folderListener;
|
|
if(NS_SUCCEEDED(datasource->QueryInterface(nsIFolderListener::GetIID(), (void**)&folderListener)))
|
|
{
|
|
AddFolderListener(folderListener);
|
|
NS_RELEASE(folderListener);
|
|
}
|
|
NS_RELEASE(datasource);
|
|
}
|
|
}
|
|
}
|
|
|
|
nsMsgFolder::~nsMsgFolder(void)
|
|
{
|
|
if(mSubFolders)
|
|
{
|
|
PRUint32 count = mSubFolders->Count();
|
|
|
|
for (int i = count - 1; i >= 0; i--)
|
|
mSubFolders->RemoveElementAt(i);
|
|
|
|
NS_RELEASE(mSubFolders);
|
|
}
|
|
|
|
if (mListeners) {
|
|
for (PRInt32 i = mListeners->Count() - 1; i >= 0; --i) {
|
|
mListeners->RemoveElementAt(i);
|
|
}
|
|
NS_RELEASE(mListeners);
|
|
}
|
|
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS_INHERITED(nsMsgFolder, nsRDFResource, nsIMsgFolder)
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
typedef PRBool
|
|
(*nsArrayFilter)(nsISupports* element, void* data);
|
|
|
|
static nsresult
|
|
nsFilterBy(nsISupportsArray* array, nsArrayFilter filter, void* data,
|
|
nsISupportsArray* *result)
|
|
{
|
|
nsISupportsArray* f;
|
|
nsresult rv = NS_NewISupportsArray(&f);
|
|
if (NS_FAILED(rv)) return rv;
|
|
NS_ADDREF(f);
|
|
for (PRUint32 i = 0; i < array->Count(); i++) {
|
|
nsISupports* element = (*array)[i];
|
|
if (filter(element, data)) {
|
|
nsresult rv = f->AppendElement(element);
|
|
if (NS_FAILED(rv)) {
|
|
NS_RELEASE(f);
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
*result = f;
|
|
return NS_OK;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgFolder::AddUnique(nsISupports* element)
|
|
{
|
|
// XXX fix this
|
|
return mSubFolders->AppendElement(element);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgFolder::ReplaceElement(nsISupports* element, nsISupports* newElement)
|
|
{
|
|
PR_ASSERT(0);
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgFolder::GetSubFolders(nsIEnumerator* *result)
|
|
{
|
|
return mSubFolders->Enumerate(result);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::AddFolderListener(nsIFolderListener * listener)
|
|
{
|
|
nsresult rv;
|
|
if (! mListeners)
|
|
{
|
|
rv = NS_NewISupportsArray(&mListeners);
|
|
if (!NS_SUCCEEDED(rv))
|
|
return rv;
|
|
}
|
|
mListeners->AppendElement(listener);
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::RemoveFolderListener(nsIFolderListener * listener)
|
|
{
|
|
if (! mListeners)
|
|
return NS_OK;
|
|
mListeners->RemoveElement(listener);
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgFolder::GetMessages(nsIEnumerator* *result)
|
|
{
|
|
// XXX should this return an empty enumeration?
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgFolder::GetThreads(nsIEnumerator ** threadEnumerator)
|
|
{
|
|
// XXX should this return an empty enumeration?
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgFolder::GetThreadForMessage(nsIMessage *message, nsIMsgThread **thread)
|
|
{
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NS_IMETHODIMP nsMsgFolder::BuildFolderURL(char **url)
|
|
{
|
|
if(*url)
|
|
{
|
|
*url = NULL;
|
|
return NS_OK;
|
|
}
|
|
else
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
|
|
#ifdef HAVE_DB
|
|
// this class doesn't have a url
|
|
NS_IMETHODIMP nsMsgFolder::BuildUrl(nsMsgDatabase *db, nsMsgKey key, char ** url)
|
|
{
|
|
if(*url)
|
|
{
|
|
*url = NULL;
|
|
return NS_OK;
|
|
}
|
|
else
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
#endif
|
|
|
|
#ifdef HAVE_MASTER
|
|
NS_IMETHODIMP nsMsgFolder::SetMaster(MSG_Master *master)
|
|
{
|
|
mMaster = master;
|
|
return NS_OK;
|
|
}
|
|
#endif
|
|
|
|
#ifdef DOES_FOLDEROPERATIONS
|
|
NS_IMETHODIMP
|
|
nsMsgFolder::StartAsyncCopyMessagesInto(MSG_FolderInfo *dstFolder,
|
|
MSG_Pane* sourcePane,
|
|
nsMsgDatabase *sourceDB,
|
|
nsMsgKeyArray *srcArray,
|
|
int32 srcCount,
|
|
MWContext *currentContext,
|
|
MSG_UrlQueue *urlQueue,
|
|
PRBool deleteAfterCopy,
|
|
nsMsgKey nextKey = nsMsgKey_None)
|
|
{
|
|
// General note: If either the source or destination folder is an IMAP folder then we add the copy info struct
|
|
// to the end of the current context's chain of copy info structs then fire off an IMAP URL.
|
|
// However, local folders don't work this way! We must add the copy info struct to the URL queue where it will be fired
|
|
// at its leisure.
|
|
|
|
MessageCopyInfo *copyInfo = (MessageCopyInfo *) XP_ALLOC(sizeof(MessageCopyInfo));
|
|
|
|
if (copyInfo)
|
|
{
|
|
XP_BZERO (copyInfo, sizeof(MessageCopyInfo));
|
|
copyInfo->srcFolder = this;
|
|
copyInfo->dstFolder = dstFolder;
|
|
copyInfo->nextCopyInfo = NULL;
|
|
copyInfo->dstIMAPfolderUpdated=FALSE;
|
|
copyInfo->offlineFolderPositionOfMostRecentMessage = 0;
|
|
copyInfo->srcDB = sourceDB;
|
|
copyInfo->srcArray = srcArray;
|
|
copyInfo->srcCount = srcCount;
|
|
|
|
copyInfo->moveState.ismove = deleteAfterCopy;
|
|
copyInfo->moveState.sourcePane = sourcePane;
|
|
copyInfo->moveState.nextKeyToLoad = nextKeyToLoad;
|
|
copyInfo->moveState.urlForNextKeyLoad = NULL;
|
|
copyInfo->moveState.moveCompleted = FALSE;
|
|
copyInfo->moveState.finalDownLoadMessageSize = 0;
|
|
copyInfo->moveState.imap_connection = 0;
|
|
copyInfo->moveState.haveUploadedMessageSize = FALSE;
|
|
|
|
nsresult openErr = NS_OK;
|
|
PRBool wasCreated;
|
|
if (dstFolder->GetType() == FOLDER_MAIL)
|
|
openErr = MailDB::Open (dstFolder->GetMailFolderInfo()->GetPathname(), FALSE, ©Info->moveState.destDB, FALSE);
|
|
else if (dstFolder->GetType() == FOLDER_IMAPMAIL && !IsNews())
|
|
openErr = ImapMailDB::Open (dstFolder->GetMailFolderInfo()->GetPathname(), FALSE, ©Info->moveState.destDB,
|
|
sourcePane->GetMaster(), &wasCreated);
|
|
|
|
|
|
if (!dstFolder->GetMailFolderInfo() || (openErr != NS_OK))
|
|
copyInfo->moveState.destDB = NULL;
|
|
|
|
// let the front end know that we are starting a long update
|
|
sourcePane->StartingUpdate(MSG_NotifyNone, 0, 0);
|
|
|
|
if ((this->GetType() == FOLDER_IMAPMAIL) || (dstFolder->GetType() == FOLDER_IMAPMAIL))
|
|
{
|
|
// add this copyinfo struct to the end
|
|
if (currentContext->msgCopyInfo != NULL)
|
|
{
|
|
MessageCopyInfo *endingNode = currentContext->msgCopyInfo;
|
|
while (endingNode->nextCopyInfo != NULL)
|
|
endingNode = endingNode->nextCopyInfo;
|
|
endingNode->nextCopyInfo = copyInfo;
|
|
}
|
|
else
|
|
currentContext->msgCopyInfo = copyInfo;
|
|
// BeginCopyMessages will fire an IMAP url. The IMAP
|
|
// module will call FinishCopyMessages so that the whole
|
|
// shebang is handled as one IMAP url. Previously the copy
|
|
// happened with a mailbox url and IMAP url running together
|
|
// in the same context. This worked on mac only.
|
|
nsresult copyErr = BeginCopyingMessages(dstFolder, sourceDB, srcArray,urlQueue,srcCount,copyInfo);
|
|
if (NS_OK != copyErr)
|
|
{
|
|
CleanupCopyMessagesInto(¤tContext->msgCopyInfo);
|
|
|
|
if (/* !NET_IsOffline() && */((int32) copyErr < -1) )
|
|
#if 0
|
|
FE_Alert (sourcePane->GetContext(), XP_GetString(copyErr));
|
|
#else
|
|
printf("%s\n", XP_GetString(copyErr));
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// okay, add this URL to our URL queue.
|
|
URL_Struct *url_struct = NET_CreateURLStruct("mailbox:copymessages", NET_DONT_RELOAD);
|
|
if (url_struct)
|
|
{
|
|
MSG_UrlQueue::AddLocalMsgCopyUrlToPane(copyInfo, url_struct, PostMessageCopyUrlExitFunc, sourcePane, FALSE);
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsMsgFolder::BeginCopyingMessages(MSG_FolderInfo *dstFolder,
|
|
nsMsgDatabase *sourceDB,
|
|
nsMsgKeyArray *srcArray,
|
|
MSG_UrlQueue *urlQueue,
|
|
int32 srcCount,
|
|
MessageCopyInfo *copyInfo)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsMsgFolder::FinishCopyingMessages(MWContext *context,
|
|
MSG_FolderInfo * srcFolder,
|
|
MSG_FolderInfo *dstFolder,
|
|
nsMsgDatabase *sourceDB,
|
|
nsMsgKeyArray **ppSrcArray,
|
|
int32 srcCount,
|
|
msg_move_state *state)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsMsgFolder::CleanupCopyMessagesInto (MessageCopyInfo **info)
|
|
{
|
|
if (!info || !*info)
|
|
return;
|
|
|
|
MSG_Pane *sourcePane = (*info)->moveState.sourcePane;
|
|
|
|
PRBool searchPane = sourcePane ? sourcePane->GetPaneType() == MSG_SEARCHPANE : FALSE;
|
|
|
|
if ((*info)->moveState.destDB != NULL)
|
|
{
|
|
(*info)->moveState.destDB->SafeClose((*info)->moveState.destDB);
|
|
(*info)->moveState.destDB = NULL;
|
|
}
|
|
if ((*info)->dstFolder->TestSemaphore(this))
|
|
(*info)->dstFolder->ReleaseSemaphore(this);
|
|
|
|
// if we were a search pane, and an error occurred, close the view on this action..
|
|
if (sourcePane != NULL && searchPane)
|
|
((MSG_SearchPane *) sourcePane)->CloseView((*info)->srcFolder);
|
|
|
|
|
|
// tell the fe that we are finished with
|
|
// out backend driven update. They can
|
|
// now do things like load the next message.
|
|
|
|
// now that an imap copy message is at most 2 urls, we can end the
|
|
// the update here. Now this is this only ending update and resource
|
|
// cleanup for message copying
|
|
sourcePane->EndingUpdate(MSG_NotifyNone, 0, 0);
|
|
|
|
// tell the FE that we're done copying so they can re-enable
|
|
// selection if they've decided to disable it during the copy
|
|
|
|
// I don't think we want to do this if we are a search pane but i haven't been able to
|
|
// justify why yet!!
|
|
|
|
if (!searchPane)
|
|
FE_PaneChanged(sourcePane, TRUE, MSG_PaneNotifyCopyFinished, 0);
|
|
|
|
// EndingUpdate may have caused an interruption of this context and cleaning up the
|
|
// url queue may have deleted this MessageCopyInfo already
|
|
if (*info)
|
|
{
|
|
MessageCopyInfo *deleteMe = *info;
|
|
*info = deleteMe->nextCopyInfo; // but nextCopyInfo == NULL. this causes the fault later on
|
|
XP_FREE(deleteMe);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::SaveMessages(nsMsgKeyArray *, const char *fileName,
|
|
MSG_Pane *pane, nsMsgDatabase *msgDB,
|
|
int (*doneCB)(void *, int status) = NULL, void *state = NULL,
|
|
PRBool addMozillaStatus = TRUE)
|
|
{
|
|
DownloadArticlesToFolder::SaveMessages(array, fileName, pane, this, msgDB, doneCB, state, addMozillaStatus);
|
|
return NS_OK;
|
|
}
|
|
#endif
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetPrettyName(char ** name)
|
|
{
|
|
char *cmName = mName.ToNewCString();
|
|
if (name) *name = PL_strdup(cmName);
|
|
delete[] cmName;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::SetPrettyName(char *name)
|
|
{
|
|
mName = name;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP_(PRUint32) nsMsgFolder::Count(void) const
|
|
{
|
|
return mSubFolders->Count();
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::AppendElement(nsISupports *aElement)
|
|
{
|
|
return mSubFolders->AppendElement(aElement);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::RemoveElement(nsISupports *aElement)
|
|
{
|
|
return mSubFolders->RemoveElement(aElement);
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsMsgFolder::Enumerate(nsIEnumerator* *result)
|
|
{
|
|
// nsMsgFolders only have subfolders, no message elements
|
|
return mSubFolders->Enumerate(result);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::Clear(void)
|
|
{
|
|
return mSubFolders->Clear();
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetName(char **name)
|
|
{
|
|
char *cmName = mName.ToNewCString();
|
|
if (name) *name = PL_strdup(cmName);
|
|
delete[] cmName;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::SetName(char * name)
|
|
{
|
|
mName = name;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetChildNamed(const char* name, nsISupports* *result)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetParent(nsIFolder* *parent)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetPrettiestName(char **name)
|
|
{
|
|
if (NS_SUCCEEDED(GetPrettyName(name)))
|
|
return NS_OK;
|
|
return GetName(name);
|
|
}
|
|
|
|
static PRBool
|
|
nsCanBeInFolderPane(nsISupports* element, void* data)
|
|
{
|
|
#ifdef HAVE_PANE
|
|
nsIMsgFolder* subFolder = NS_STATIC_CAST(nsIMsgFolder*, element);
|
|
return subFolder->CanBeInFolderPane();
|
|
#else
|
|
return PR_TRUE;
|
|
#endif
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgFolder::GetVisibleSubFolders(nsIEnumerator* *result)
|
|
{
|
|
nsresult rv;
|
|
nsISupportsArray* vFolders;
|
|
rv = nsFilterBy(mSubFolders, nsCanBeInFolderPane, nsnull, &vFolders);
|
|
if (NS_FAILED(rv)) return rv;
|
|
rv = vFolders->Enumerate(result);
|
|
NS_RELEASE(vFolders);
|
|
return rv;
|
|
}
|
|
|
|
#ifdef HAVE_ADMINURL
|
|
NS_IMETHODIMP nsMsgFolder::GetAdminUrl(MWContext *context, MSG_AdminURLType type)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::HaveAdminUrl(MSG_AdminURLType type, PRBool *haveAdminUrl)
|
|
{
|
|
if(haveAdminUrl)
|
|
{
|
|
*haveAdminUrl = PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
return
|
|
NS_ERROR_NULL_POINTER;
|
|
}
|
|
#endif
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetDeleteIsMoveToTrash(PRBool *deleteIsMoveToTrash)
|
|
{
|
|
if(deleteIsMoveToTrash)
|
|
{
|
|
*deleteIsMoveToTrash = PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
return
|
|
NS_ERROR_NULL_POINTER;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetShowDeletedMessages(PRBool *showDeletedMessages)
|
|
{
|
|
if(showDeletedMessages)
|
|
{
|
|
*showDeletedMessages = PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
return
|
|
NS_ERROR_NULL_POINTER;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsMsgFolder::OnCloseFolder ()
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::Delete ()
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::PropagateDelete(nsIMsgFolder **folder, PRBool deleteStorage)
|
|
{
|
|
nsresult status = NS_OK;
|
|
|
|
nsIMsgFolder *child = nsnull;
|
|
|
|
// first, find the folder we're looking to delete
|
|
for (PRUint32 i = 0; i < mSubFolders->Count() && *folder; i++)
|
|
{
|
|
nsISupports *supports = mSubFolders->ElementAt(i);
|
|
if(supports)
|
|
{
|
|
if(NS_SUCCEEDED(status = supports->QueryInterface(nsIMsgFolder::GetIID(), (void**)&child)))
|
|
{
|
|
if (*folder == child)
|
|
{
|
|
// maybe delete disk storage for it, and its subfolders
|
|
status = child->RecursiveDelete(deleteStorage);
|
|
|
|
if (status == NS_OK)
|
|
{
|
|
#ifdef HAVE_MASTER
|
|
PR_ASSERT(mMaster);
|
|
// Send out a broadcast message that this folder is going away.
|
|
// Many important things happen on this broadcast.
|
|
mMaster->BroadcastFolderDeleted (child);
|
|
#endif
|
|
mSubFolders->RemoveElement(child);
|
|
NS_RELEASE(*folder); // stop looking since will set *folder to nsnull
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PRUint32 folderDepth, childDepth;
|
|
|
|
if(NS_SUCCEEDED((*folder)->GetDepth(&folderDepth)) &&
|
|
NS_SUCCEEDED(child->GetDepth(&childDepth)) &&
|
|
folderDepth > childDepth)
|
|
{
|
|
status = child->PropagateDelete (folder, deleteStorage);
|
|
}
|
|
}
|
|
NS_RELEASE(child);
|
|
}
|
|
NS_RELEASE(supports);
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::RecursiveDelete(PRBool deleteStorage)
|
|
{
|
|
// If deleteStorage is TRUE, recursively deletes disk storage for this folder
|
|
// and all its subfolders.
|
|
// Regardless of deleteStorage, always unlinks them from the children lists and
|
|
// frees memory for the subfolders but NOT for _this_
|
|
|
|
nsresult status = NS_OK;
|
|
|
|
while (mSubFolders->Count() > 0)
|
|
{
|
|
nsISupports *supports = mSubFolders->ElementAt(0);
|
|
nsIMsgFolder *child = nsnull;
|
|
|
|
if(NS_SUCCEEDED(status = supports->QueryInterface(nsIMsgFolder::GetIID(), (void**)&child)))
|
|
{
|
|
status = child->RecursiveDelete(deleteStorage); // recur
|
|
|
|
#ifdef HAVE_MASTER
|
|
// Send out a broadcast message that this folder is going away.
|
|
// Many important things happen on this broadcast.
|
|
mMaster->BroadcastFolderDeleted (child);
|
|
#endif
|
|
mSubFolders->RemoveElement(child); // unlink it from this's child list
|
|
NS_RELEASE(child);
|
|
}
|
|
NS_RELEASE(supports); // free memory
|
|
}
|
|
|
|
// now delete the disk storage for _this_
|
|
if (deleteStorage && (status == NS_OK))
|
|
status = Delete();
|
|
|
|
return status;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::CreateSubfolder(const char *folderName)
|
|
{
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsMsgFolder::Rename(const char *name)
|
|
{
|
|
nsresult status = NS_OK;
|
|
status = SetName((char*)name);
|
|
//After doing a SetName we need to make sure that broadcasting this message causes a
|
|
//new sort to happen.
|
|
#ifdef HAVE_MASTER
|
|
if (m_master)
|
|
m_master->BroadcastFolderChanged(this);
|
|
#endif
|
|
return status;
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::Adopt(const nsIMsgFolder *srcFolder, PRUint32* outPos)
|
|
{
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::ContainsChildNamed(const char *name, PRBool* containsChild)
|
|
{
|
|
nsIMsgFolder *child;
|
|
|
|
if(containsChild)
|
|
{
|
|
*containsChild = PR_FALSE;
|
|
if(NS_SUCCEEDED(GetChildNamed(name, (nsISupports**)&child)))
|
|
{
|
|
*containsChild = child != nsnull;
|
|
if(child)
|
|
NS_RELEASE(child);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
else
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::FindParentOf(nsIMsgFolder * aFolder, nsIMsgFolder ** aParent)
|
|
{
|
|
if(!aParent)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*aParent = nsnull;
|
|
|
|
PRUint32 count = mSubFolders->Count();
|
|
|
|
for (PRUint32 i = 0; i < count && *aParent == NULL; i++)
|
|
{
|
|
nsISupports *supports = mSubFolders->ElementAt(i);
|
|
nsIMsgFolder *child = nsnull;
|
|
if(NS_SUCCEEDED(supports->QueryInterface(nsIMsgFolder::GetIID(), (void**)&child)))
|
|
{
|
|
if (aFolder == child)
|
|
{
|
|
*aParent = this;
|
|
NS_ADDREF(*aParent);
|
|
}
|
|
|
|
NS_RELEASE(child);
|
|
}
|
|
NS_RELEASE(supports);
|
|
}
|
|
|
|
for (PRUint32 j = 0; j < count && *aParent == NULL; j++)
|
|
{
|
|
|
|
nsISupports *supports = mSubFolders->ElementAt(j);
|
|
nsIMsgFolder *child = nsnull;
|
|
if(NS_SUCCEEDED(supports->QueryInterface(nsIMsgFolder::GetIID(), (void**)&child)))
|
|
{
|
|
child->FindParentOf(aFolder, aParent);
|
|
NS_RELEASE(child);
|
|
}
|
|
NS_RELEASE(supports);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::IsParentOf(nsIMsgFolder *child, PRBool deep, PRBool *isParent)
|
|
{
|
|
if(!isParent)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
PRUint32 count = mSubFolders->Count();
|
|
|
|
for (PRUint32 i = 0; i < count; i++)
|
|
{
|
|
nsISupports *supports = mSubFolders->ElementAt(i);
|
|
nsIMsgFolder *folder;
|
|
if(NS_SUCCEEDED(supports->QueryInterface(nsIMsgFolder::GetIID(), (void**)&folder)))
|
|
{
|
|
if (folder == child )
|
|
*isParent = PR_TRUE;
|
|
else if(deep)
|
|
{
|
|
folder->IsParentOf(child, deep, isParent);
|
|
}
|
|
}
|
|
NS_RELEASE(supports);
|
|
if(*isParent)
|
|
return NS_OK;
|
|
}
|
|
*isParent = PR_FALSE;
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GenerateUniqueSubfolderName(const char *prefix, nsIMsgFolder *otherFolder,
|
|
char **name)
|
|
{
|
|
if(!name)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
/* only try 256 times */
|
|
for (int count = 0; (count < 256); count++)
|
|
{
|
|
PRUint32 prefixSize = PL_strlen(prefix);
|
|
|
|
//allocate string big enough for prefix, 256, and '\0'
|
|
char *uniqueName = (char*)PR_MALLOC(prefixSize + 4);
|
|
PR_snprintf(uniqueName, prefixSize + 4, "%s%d",prefix,count);
|
|
PRBool containsChild;
|
|
PRBool otherContainsChild = PR_FALSE;
|
|
|
|
ContainsChildNamed(uniqueName, &containsChild);
|
|
if(otherFolder)
|
|
{
|
|
((nsIMsgFolder*)otherFolder)->ContainsChildNamed(uniqueName, &otherContainsChild);
|
|
}
|
|
|
|
if (!containsChild && !otherContainsChild)
|
|
{
|
|
*name = uniqueName;
|
|
return NS_OK;
|
|
}
|
|
else
|
|
PR_FREEIF(uniqueName);
|
|
}
|
|
*name = nsnull;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetDepth(PRUint32 *depth)
|
|
{
|
|
if(!depth)
|
|
return NS_ERROR_NULL_POINTER;
|
|
*depth = mDepth;
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::SetDepth(PRUint32 depth)
|
|
{
|
|
mDepth = depth;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::UpdateSummaryTotals()
|
|
{
|
|
//We don't support this
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::SummaryChanged()
|
|
{
|
|
UpdateSummaryTotals();
|
|
#ifdef HAVE_MASTER
|
|
if (mMaster)
|
|
mMaster->BroadcastFolderChanged(this);
|
|
#endif
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetNumUnread(PRBool deep, PRUint32 *numUnread)
|
|
{
|
|
if(!numUnread)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
PRUint32 total = mNumUnreadMessages;
|
|
if (deep)
|
|
{
|
|
nsIMsgFolder *folder;
|
|
PRUint32 count = mSubFolders->Count();
|
|
|
|
for (PRUint32 i = 0; i < count; i++)
|
|
{
|
|
nsISupports *supports = mSubFolders->ElementAt(i);
|
|
|
|
if(NS_SUCCEEDED(supports->QueryInterface(nsIMsgFolder::GetIID(), (void**)&folder)))
|
|
{
|
|
if (folder)
|
|
{
|
|
PRUint32 num;
|
|
folder->GetNumUnread(deep, &num);
|
|
if (num >= 0) // it's legal for counts to be negative if we don't know
|
|
total += num;
|
|
}
|
|
NS_RELEASE(folder);
|
|
}
|
|
NS_RELEASE(supports);
|
|
}
|
|
}
|
|
*numUnread = total;
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetTotalMessages(PRBool deep, PRUint32 *totalMessages)
|
|
{
|
|
if(!totalMessages)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
PRUint32 total = mNumTotalMessages;
|
|
if (deep)
|
|
{
|
|
nsIMsgFolder *folder;
|
|
PRUint32 count = mSubFolders->Count();
|
|
|
|
for (PRUint32 i = 0; i < count; i++)
|
|
{
|
|
nsISupports *supports = mSubFolders->ElementAt(i);
|
|
|
|
if(NS_SUCCEEDED(supports->QueryInterface(nsIMsgFolder::GetIID(), (void**)&folder)))
|
|
{
|
|
if (folder)
|
|
{
|
|
PRUint32 num;
|
|
folder->GetTotalMessages (deep, &num);
|
|
if (num >= 0) // it's legal for counts to be negative if we don't know
|
|
total += num;
|
|
NS_RELEASE(folder);
|
|
}
|
|
}
|
|
NS_RELEASE(supports);
|
|
}
|
|
}
|
|
*totalMessages = total;
|
|
return NS_OK;
|
|
}
|
|
|
|
#ifdef HAVE_DB
|
|
NS_IMETHOD GetTotalMessagesInDB(PRUint32 *totalMessages) const; // How many messages in database.
|
|
#endif
|
|
|
|
#ifdef HAVE_PANE
|
|
virtual void MarkAllRead(MSG_Pane *pane, PRBool deep);
|
|
#endif
|
|
|
|
#ifdef HAVE_DB
|
|
// These functions are used for tricking the front end into thinking that we have more
|
|
// messages than are really in the DB. This is usually after and IMAP message copy where
|
|
// we don't want to do an expensive select until the user actually opens that folder
|
|
// These functions are called when MSG_Master::GetFolderLineById is populating a MSG_FolderLine
|
|
// struct used by the FE
|
|
int32 GetNumPendingUnread(PRBool deep = FALSE) const;
|
|
int32 GetNumPendingTotalMessages(PRBool deep = FALSE) const;
|
|
|
|
void ChangeNumPendingUnread(int32 delta);
|
|
void ChangeNumPendingTotalMessages(int32 delta);
|
|
|
|
|
|
NS_IMETHODIMP nsMsgFolder::SetFolderPrefFlags(PRUint32 flags)
|
|
{
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetFolderPrefFlags(PRUint32 *flags)
|
|
{
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::SetFolderCSID(PRInt16 csid)
|
|
{
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetFolderCSID(PRInt16 *csid)
|
|
{
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::SetLastMessageLoaded(nsMsgKey lastMessageLoaded)
|
|
{
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetLastMessageLoaded()
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
NS_IMETHODIMP nsMsgFolder::SetFlag(PRUint32 flag)
|
|
{
|
|
// OnFlagChange can be expensive, so don't call it if we don't need to
|
|
PRBool flagSet;
|
|
nsresult rv;
|
|
|
|
if(!NS_SUCCEEDED(rv = GetFlag(flag, &flagSet)))
|
|
return rv;
|
|
|
|
if (!flagSet)
|
|
{
|
|
mFlags |= flag;
|
|
OnFlagChange(flag);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::ClearFlag(PRUint32 flag)
|
|
{
|
|
// OnFlagChange can be expensive, so don't call it if we don't need to
|
|
PRBool flagSet;
|
|
nsresult rv;
|
|
|
|
if(!NS_SUCCEEDED(rv = GetFlag(flag, &flagSet)))
|
|
return rv;
|
|
|
|
if (!flagSet)
|
|
{
|
|
mFlags &= ~flag;
|
|
OnFlagChange (flag);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetFlag(PRUint32 flag, PRBool *_retval)
|
|
{
|
|
*_retval = ((mFlags & flag) != 0);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::ToggleFlag(PRUint32 flag)
|
|
{
|
|
mFlags ^= flag;
|
|
OnFlagChange (flag);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::OnFlagChange(PRUint32 flag)
|
|
{
|
|
//Still need to implement
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetFlags(PRUint32 *_retval)
|
|
{
|
|
*_retval = mFlags;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetFoldersWithFlag(PRUint32 flags, nsIMsgFolder **result,
|
|
PRUint32 resultsize, PRUint32 *numFolders)
|
|
{
|
|
PRUint32 num = 0;
|
|
if ((flags & mFlags) == flags) {
|
|
if (result && (num < resultsize)) {
|
|
result[num] = this;
|
|
}
|
|
num++;
|
|
}
|
|
|
|
nsIMsgFolder *folder = nsnull;
|
|
for (PRUint32 i=0; i < (PRUint32)mSubFolders->Count(); i++) {
|
|
nsISupports *supports = mSubFolders->ElementAt(i);
|
|
if(NS_SUCCEEDED(supports->QueryInterface(nsIMsgFolder::GetIID(), (void**)&folder)))
|
|
{
|
|
// CAREFUL! if NULL is passed in for result then the caller
|
|
// still wants the full count! Otherwise, the result should be at most the
|
|
// number that the caller asked for.
|
|
PRUint32 numSubFolders;
|
|
|
|
if (!result)
|
|
{
|
|
folder->GetFoldersWithFlag(flags, NULL, 0, &numSubFolders);
|
|
num += numSubFolders;
|
|
}
|
|
else if (num < resultsize)
|
|
{
|
|
folder->GetFoldersWithFlag(flags, result + num, resultsize - num, &numSubFolders);
|
|
num += numSubFolders;
|
|
}
|
|
else
|
|
{
|
|
NS_RELEASE(folder);
|
|
NS_RELEASE(supports);
|
|
break;
|
|
}
|
|
NS_RELEASE(folder);
|
|
}
|
|
NS_RELEASE(supports);
|
|
}
|
|
|
|
*numFolders = num;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetExpansionArray(nsISupportsArray *expansionArray)
|
|
{
|
|
// the application of flags in GetExpansionArray is subtly different
|
|
// than in GetFoldersWithFlag
|
|
|
|
for (PRUint32 i = 0; i < mSubFolders->Count(); i++)
|
|
{
|
|
nsISupports *supports = mSubFolders->ElementAt(i);
|
|
nsIMsgFolder *folder = nsnull;
|
|
|
|
if(NS_SUCCEEDED(supports->QueryInterface(nsIMsgFolder::GetIID(), (void**)&folder)))
|
|
{
|
|
((nsISupportsArray*)expansionArray)->InsertElementAt(folder, expansionArray->Count());
|
|
PRUint32 flags;
|
|
folder->GetFlags(&flags);
|
|
if (!(flags & MSG_FOLDER_FLAG_ELIDED))
|
|
folder->GetExpansionArray(expansionArray);
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
#ifdef HAVE_PANE
|
|
NS_IMETHODIMP nsMsgFolder::SetFlagInAllFolderPanes(PRUInt32 which)
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_NET
|
|
NS_IMETHODIMP nsMsgFolder::EscapeMessageId(const char *messageId, const char **escapeMessageID)
|
|
{
|
|
|
|
}
|
|
#endif
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetExpungedBytesCount(PRUint32 *count)
|
|
{
|
|
if(!count)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*count = 0;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetDeletable(PRBool *deletable)
|
|
{
|
|
|
|
if(!deletable)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*deletable = PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetCanCreateChildren(PRBool *canCreateChildren)
|
|
{
|
|
if(!canCreateChildren)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*canCreateChildren = PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetCanBeRenamed(PRBool *canBeRenamed)
|
|
{
|
|
if(!canBeRenamed)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*canBeRenamed = PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetRequiresCleanup(PRBool *requiredCleanup)
|
|
{
|
|
if(!requiredCleanup)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*requiredCleanup = PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::ClearRequiresCleanup()
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
#ifdef HAVE_PANE
|
|
NS_IMETHODIMP nsMsgFolder::CanBeInFolderPane(PRBool *canBeInFolderPane)
|
|
{
|
|
|
|
}
|
|
#endif
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetKnowsSearchNntpExtension(PRBool *knowsExtension)
|
|
{
|
|
if(!knowsExtension)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*knowsExtension = PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetAllowsPosting(PRBool *allowsPosting)
|
|
{
|
|
if(!allowsPosting)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*allowsPosting = PR_TRUE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::DisplayRecipients(PRBool *displayRecipients)
|
|
{
|
|
nsresult rv;
|
|
|
|
*displayRecipients = PR_FALSE;
|
|
|
|
if (mFlags & MSG_FOLDER_FLAG_SENTMAIL && !(mFlags & MSG_FOLDER_FLAG_INBOX))
|
|
*displayRecipients = PR_TRUE;
|
|
else if (mFlags & MSG_FOLDER_FLAG_QUEUE)
|
|
*displayRecipients = PR_TRUE;
|
|
else
|
|
{
|
|
// Only mail folders can be FCC folders
|
|
if (mFlags & MSG_FOLDER_FLAG_MAIL || mFlags & MSG_FOLDER_FLAG_IMAPBOX)
|
|
{
|
|
// There's one FCC folder for sent mail, and one for sent news
|
|
nsIMsgFolder *fccFolders[2];
|
|
int numFccFolders = 0;
|
|
#ifdef HAVE_MASTER
|
|
m_master->GetFolderTree()->GetFoldersWithFlag (MSG_FOLDER_FLAG_SENTMAIL, fccFolders, 2, &numFccFolders);
|
|
#endif
|
|
for (int i = 0; i < numFccFolders; i++)
|
|
{
|
|
PRBool isParent;
|
|
if(NS_SUCCEEDED(rv = fccFolders[i]->IsParentOf(this, PR_TRUE, &isParent)))
|
|
{
|
|
if (isParent)
|
|
*displayRecipients = PR_TRUE;
|
|
}
|
|
NS_RELEASE(fccFolders[i]);
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::ReadDBFolderInfo(PRBool force)
|
|
{
|
|
// Since it turns out to be pretty expensive to open and close
|
|
// the DBs all the time, if we have to open it once, get everything
|
|
// we might need while we're here
|
|
|
|
nsresult result= NS_OK;
|
|
if (force || !(mPrefFlags & MSG_FOLDER_PREF_CACHED))
|
|
{
|
|
nsIDBFolderInfo *folderInfo;
|
|
nsIMsgDatabase *db;
|
|
result = NS_SUCCEEDED(GetDBFolderInfoAndDB(&folderInfo, &db));
|
|
if(result)
|
|
{
|
|
mIsCachable = TRUE;
|
|
if (folderInfo)
|
|
{
|
|
|
|
folderInfo->GetFlags(&mPrefFlags);
|
|
mPrefFlags |= MSG_FOLDER_PREF_CACHED;
|
|
folderInfo->SetFlags(mPrefFlags);
|
|
|
|
folderInfo->GetNumMessages(&mNumTotalMessages);
|
|
folderInfo->GetNumNewMessages(&mNumUnreadMessages);
|
|
|
|
//These should be put in IMAP folder only.
|
|
//folderInfo->GetImapTotalPendingMessages(&mNumPendingTotalMessages);
|
|
//folderInfo->GetImapUnreadPendingMessages(&mNumPendingUnreadMessages);
|
|
|
|
// folderInfo->GetCSID(&mCsid);
|
|
|
|
if (db && !db->HasNew() && mNumPendingUnreadMessages <= 0)
|
|
ClearFlag(MSG_FOLDER_FLAG_GOT_NEW);
|
|
}
|
|
|
|
if (db)
|
|
db->Close(PR_FALSE);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::AcquireSemaphore(nsISupports *semHolder)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
if (mSemaphoreHolder == NULL)
|
|
{
|
|
mSemaphoreHolder = semHolder;
|
|
mSemaphoreHolder->AddRef();
|
|
}
|
|
else
|
|
rv = NS_MSG_FOLDER_BUSY;
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::ReleaseSemaphore(nsISupports *semHolder)
|
|
{
|
|
if (!mSemaphoreHolder || mSemaphoreHolder == semHolder)
|
|
{
|
|
if(mSemaphoreHolder)
|
|
mSemaphoreHolder->Release();
|
|
mSemaphoreHolder = NULL;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::TestSemaphore(nsISupports *semHolder, PRBool *result)
|
|
{
|
|
if(!result)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*result = (mSemaphoreHolder == semHolder);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::IsLocked(PRBool *isLocked)
|
|
{
|
|
*isLocked = mSemaphoreHolder != NULL;
|
|
return NS_OK;
|
|
}
|
|
|
|
#ifdef HAVE_PANE
|
|
MWContext *GetFolderPaneContext();
|
|
#endif
|
|
|
|
#ifdef HAVE_MASTER
|
|
MSG_Master *GetMaster() {return m_master;}
|
|
#endif
|
|
|
|
#ifdef HAVE_CACHE
|
|
NS_IMETHODIMP nsMsgFolder::WriteToCache(XP_File)
|
|
{
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::ReadFromCache(char *)
|
|
{
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::IsCachable(PRBool *isCachable)
|
|
{
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::SkipCacheTokens(char **ppBuf, int numTokens)
|
|
{
|
|
|
|
}
|
|
#endif
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetRelativePathName(char **pathName)
|
|
{
|
|
if(!pathName)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*pathName = nsnull;
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetSizeOnDisk(PRUint32 *size)
|
|
{
|
|
if(!size)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*size = 0;
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
#ifdef HAVE_NET
|
|
NS_IMETHODIMP nsMsgFolder::ShouldPerformOperationOffline(PRBool *performOffline)
|
|
{
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifdef DOES_FOLDEROPERATIONS
|
|
NS_IMETHODIMP nsMsgFolder::DownloadToTempFileAndUpload(MessageCopyInfo *copyInfo,
|
|
nsMsgKeyArray &keysToSave,
|
|
MSG_FolderInfo *dstFolder,
|
|
nsMsgDatabase *sourceDB)
|
|
{
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::UpdateMoveCopyStatus(MWContext *context, PRBool isMove, int32 curMsgCount, int32 totMessages)
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
NS_IMETHODIMP nsMsgFolder::RememberPassword(const char *password)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetRememberedPassword(char ** password)
|
|
{
|
|
|
|
if(!password)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*password = nsnull;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::UserNeedsToAuthenticateForFolder(PRBool displayOnly, PRBool *needsAuthenticate)
|
|
{
|
|
if(!needsAuthenticate)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*needsAuthenticate = PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetUsersName(char **userName)
|
|
{
|
|
if(!userName)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*userName = "";
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgFolder::GetHostName(char **hostName)
|
|
{
|
|
if(!hostName)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*hostName = "";
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsMsgFolder::NotifyPropertyChanged(char *property, char *oldValue, char* newValue)
|
|
{
|
|
nsISupports *supports;
|
|
if(NS_SUCCEEDED(QueryInterface(kISupportsIID, (void**)&supports)))
|
|
{
|
|
PRUint32 i;
|
|
for(i = 0; i < mListeners->Count(); i++)
|
|
{
|
|
nsIFolderListener *listener = (nsIFolderListener*)mListeners->ElementAt(i);
|
|
listener->OnItemPropertyChanged(supports, property, oldValue, newValue);
|
|
NS_RELEASE(listener);
|
|
}
|
|
NS_RELEASE(supports);
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
nsresult nsMsgFolder::NotifyItemAdded(nsISupports *item)
|
|
{
|
|
|
|
PRUint32 i;
|
|
for(i = 0; i < mListeners->Count(); i++)
|
|
{
|
|
nsIFolderListener *listener = (nsIFolderListener*)mListeners->ElementAt(i);
|
|
listener->OnItemAdded(this, item);
|
|
NS_RELEASE(listener);
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
nsresult nsMsgFolder::NotifyItemDeleted(nsISupports *item)
|
|
{
|
|
|
|
PRUint32 i;
|
|
for(i = 0; i < mListeners->Count(); i++)
|
|
{
|
|
nsIFolderListener *listener = (nsIFolderListener*)mListeners->ElementAt(i);
|
|
listener->OnItemRemoved(this, item);
|
|
NS_RELEASE(listener);
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// URI Utilities for RDF
|
|
|
|
#include "prprf.h"
|
|
#include "prsystem.h"
|
|
|
|
static char *gMailboxRoot = nsnull;
|
|
static char *gNewsRoot = nsnull;
|
|
static const char *gImapRoot = nsnull;
|
|
|
|
nsresult
|
|
nsGetNewsRoot(nsFileSpec &result)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
if (gNewsRoot == nsnull) {
|
|
nsIMsgMailSession *session;
|
|
rv = nsServiceManager::GetService(kMsgMailSessionCID,
|
|
nsIMsgMailSession::GetIID(),
|
|
(nsISupports **)&session);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
nsIMsgIncomingServer *server;
|
|
rv = session->GetCurrentServer(&server);
|
|
if (NS_FAILED(rv)) printf("nsGetNewsRoot: Couldn't get current server\n");
|
|
if (NS_SUCCEEDED(rv)) {
|
|
nsINntpIncomingServer *nntpServer;
|
|
rv = server->QueryInterface(nsINntpIncomingServer::GetIID(),
|
|
(void **)&nntpServer);
|
|
if (NS_FAILED(rv)) printf("nsGetNewsRoot: Couldn't get nntp server\n");
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = nntpServer->GetRootFolderPath(&gNewsRoot);
|
|
if (NS_FAILED(rv)) printf("nsGetNewsRoot: Couldn't get root\n");
|
|
NS_RELEASE(nntpServer);
|
|
}
|
|
NS_RELEASE(server);
|
|
|
|
}
|
|
nsServiceManager::ReleaseService(kMsgMailSessionCID, session);
|
|
}
|
|
} /* if (gNewsRoot == nsnull) .. */
|
|
result = gNewsRoot;
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsGetImapRoot(nsFileSpec &result)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
// temporary stuff. for now - should get everything from the mail session
|
|
if (gImapRoot == nsnull) {
|
|
gImapRoot = PL_strdup("/tmp");
|
|
}
|
|
result = gImapRoot;
|
|
return rv;
|
|
|
|
}
|
|
|
|
nsresult
|
|
nsGetMailboxRoot(nsFileSpec &result)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
// temporary stuff. for now get everything from the mail session
|
|
if (gMailboxRoot == nsnull) {
|
|
nsIMsgMailSession *session;
|
|
rv = nsServiceManager::GetService(kMsgMailSessionCID,
|
|
nsIMsgMailSession::GetIID(),
|
|
(nsISupports **)&session);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
nsIMsgIncomingServer *server;
|
|
rv = session->GetCurrentServer(&server);
|
|
if (NS_FAILED(rv)) printf("nsGetMailboxRoot: Couldn't get current server\n");
|
|
if (NS_SUCCEEDED(rv)) {
|
|
nsIPop3IncomingServer *popServer;
|
|
rv = server->QueryInterface(nsIPop3IncomingServer::GetIID(),
|
|
(void **)&popServer);
|
|
if (NS_FAILED(rv)) printf("nsGetMailboxRoot: Couldn't get pop3 server\n");
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = popServer->GetRootFolderPath(&gMailboxRoot);
|
|
if (NS_FAILED(rv)) printf("nsGetMailboxRoot: Couldn't get root\n");
|
|
NS_RELEASE(popServer);
|
|
}
|
|
NS_RELEASE(server);
|
|
|
|
}
|
|
nsServiceManager::ReleaseService(kMsgMailSessionCID, session);
|
|
}
|
|
} /* if (gMailboxRoot == nsnull) .. */
|
|
result = gMailboxRoot;
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsGetMailFolderSeparator(nsString& result)
|
|
{
|
|
static char* gMailFolderSep = nsnull; // never freed
|
|
|
|
if (gMailFolderSep == nsnull) {
|
|
gMailFolderSep = PR_smprintf(".sbd");
|
|
if (gMailFolderSep == nsnull)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
result = gMailFolderSep;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsURI2Path(const char* rootURI, const char* uriStr, nsFileSpec& pathResult)
|
|
{
|
|
nsresult rv;
|
|
|
|
#ifdef DEBUG_sspitzer
|
|
/* examples: */
|
|
/* nsURI2Path(mailbox:/, mailbox:/, ??)->/home/sspitzer/mozillamail */
|
|
/* nsURI2Path(mailbox:/, mailbox://Drafts, ??)->/home/sspitzer/mozillamail/Drafts */
|
|
/* nsURI2Path(news:/, news:/, ??)->/home/sspitzer/mozillanews */
|
|
printf("nsURI2Path(%s, %s, ??)", rootURI, uriStr);
|
|
#endif
|
|
|
|
nsAutoString sep;
|
|
sep += PR_GetDirectorySeparator();
|
|
|
|
nsAutoString sbdSep;
|
|
/* sspitzer: is this ok for mail and news? */
|
|
rv = nsGetMailFolderSeparator(sbdSep);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsAutoString uri = uriStr;
|
|
if (uri.Find(rootURI) != 0) // if doesn't start with rootURI
|
|
return NS_ERROR_FAILURE;
|
|
|
|
/* sspitzer: yes, this is inefficent. it may be going away
|
|
* if not, I'll make it more efficient later. */
|
|
if ((strcmp(rootURI, kMailboxRootURI) == 0) ||
|
|
(strcmp(rootURI, kMailboxMessageRootURI) == 0)) {
|
|
// local mail case
|
|
rv = nsGetMailboxRoot(pathResult);
|
|
}
|
|
else if ((strcmp(rootURI, kNewsMessageRootURI) == 0) ||
|
|
(strcmp(rootURI, kNewsRootURI) == 0)) {
|
|
// news case
|
|
rv = nsGetNewsRoot(pathResult);
|
|
}
|
|
else if ((strcmp(rootURI, kImapMessageRootURI) == 0) ||
|
|
(strcmp(rootURI, kImapRootURI) == 0)) {
|
|
rv = nsGetImapRoot(pathResult);
|
|
}
|
|
else {
|
|
rv = NS_ERROR_FAILURE;
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
|
pathResult = nsnull;
|
|
return rv;
|
|
}
|
|
|
|
nsAutoString path="";
|
|
uri.Cut(0, nsCRT::strlen(rootURI));
|
|
|
|
PRInt32 uriLen = uri.Length();
|
|
PRInt32 pos;
|
|
while(uriLen > 0) {
|
|
nsAutoString folderName;
|
|
|
|
PRInt32 leadingPos;
|
|
// if it's the first character then remove it.
|
|
while ((leadingPos = uri.Find('/')) == 0) {
|
|
uri.Cut(0, 1);
|
|
uriLen--;
|
|
}
|
|
|
|
if (uriLen == 0)
|
|
break;
|
|
|
|
pos = uri.Find('/');
|
|
if (pos < 0)
|
|
pos = uriLen;
|
|
|
|
|
|
PRInt32 leftRes = uri.Left(folderName, pos);
|
|
|
|
NS_ASSERTION(leftRes == pos,
|
|
"something wrong with nsString");
|
|
//We only want to add this after the first time around.
|
|
if(path.Length() > 0)
|
|
{
|
|
path += sep;
|
|
path += PR_GetDirectorySeparator();
|
|
}
|
|
// the first time around the separator is special because
|
|
// the root mail folder doesn't end with .sbd
|
|
sep = sbdSep;
|
|
|
|
path += folderName;
|
|
uri.Cut(0, pos);
|
|
uriLen -= pos;
|
|
}
|
|
|
|
if(path.Length() > 0)
|
|
pathResult +=path;
|
|
|
|
#ifdef DEBUG_sspitzer
|
|
printf("->%s\n", (const char *)pathResult);
|
|
#endif
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsPath2URI(const char* rootURI, const nsFileSpec& spec, char **uri)
|
|
{
|
|
nsresult rv;
|
|
|
|
#ifdef DEBUG_sspitzer
|
|
/* examples: */
|
|
/* nsPath2URI(mailbox_message:/, /home/sspitzer/mozillamail/Drafts, ??)->mailbox_message://Drafts */
|
|
/* nsPath2URI(news_message:/, /tmp/mozillanews/news.mozilla.org/netscape.public.mozilla.unix, ??)->news_message://news.mozilla.org/netscape.public.mozilla.unix */
|
|
printf("nsPath2URI(%s, %s, ??)", rootURI, (const char *)spec);
|
|
#endif
|
|
|
|
nsAutoString sep;
|
|
/* sspitzer: is this ok for mail and news? */
|
|
rv = nsGetMailFolderSeparator(sep);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
PRUint32 sepLen = sep.Length();
|
|
|
|
nsFileSpec root;
|
|
if (strcmp(rootURI, kNewsMessageRootURI) == 0) {
|
|
rv = nsGetNewsRoot(root);
|
|
}
|
|
else if (strcmp(rootURI, kImapMessageRootURI) == 0) {
|
|
rv = nsGetImapRoot(root);
|
|
}
|
|
else {
|
|
// local mail case
|
|
rv = nsGetMailboxRoot(root);
|
|
}
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
const char *path = spec;
|
|
nsAutoString pathStr(path);
|
|
path = root;
|
|
nsAutoString rootStr(path);
|
|
|
|
PRInt32 pos = pathStr.Find(rootStr);
|
|
if (pos != 0) // if doesn't start with root path
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsAutoString uriStr(rootURI);
|
|
|
|
PRUint32 rootStrLen = rootStr.Length();
|
|
pathStr.Cut(0, rootStrLen);
|
|
PRInt32 pathStrLen = pathStr.Length();
|
|
|
|
char dirSep = PR_GetDirectorySeparator();
|
|
|
|
while (pathStrLen > 0) {
|
|
nsAutoString folderName;
|
|
|
|
PRInt32 leadingPos;
|
|
// if it's the first character then remove it.
|
|
while ((leadingPos = pathStr.Find(dirSep)) == 0) {
|
|
pathStr.Cut(0, 1);
|
|
pathStrLen--;
|
|
}
|
|
if (pathStrLen == 0)
|
|
break;
|
|
|
|
pos = pathStr.Find(sep);
|
|
if (pos < 0)
|
|
pos = pathStrLen;
|
|
|
|
PRInt32 leftRes = pathStr.Left(folderName, pos);
|
|
NS_ASSERTION(leftRes == pos,
|
|
"something wrong with nsString");
|
|
|
|
pathStr.Cut(0, pos + sepLen);
|
|
pathStrLen -= pos + sepLen;
|
|
|
|
uriStr += '/';
|
|
uriStr += folderName;
|
|
}
|
|
*uri = uriStr.ToNewCString();
|
|
#ifdef DEBUG_sspitzer
|
|
printf("->%s\n", *uri);
|
|
#endif
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsURI2Name(const char* rootURI, char* uriStr, nsString& name)
|
|
{
|
|
nsAutoString uri = uriStr;
|
|
if (uri.Find(rootURI) != 0) // if doesn't start with rootURI
|
|
return NS_ERROR_FAILURE;
|
|
PRInt32 pos = uri.RFind("/");
|
|
PRInt32 length = uri.Length();
|
|
PRInt32 count = length - (pos + 1);
|
|
return uri.Right(name, count);
|
|
}
|
|
|
|
/* parses LocalMessageURI, NewsMessageURI, and ImapMessageURI */
|
|
nsresult nsParseMessageURI(const char* uri, nsString& folderURI, PRUint32 *key)
|
|
{
|
|
if(!key)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
nsAutoString uriStr = uri;
|
|
PRInt32 keySeparator = uriStr.Find('#');
|
|
if(keySeparator != -1)
|
|
{
|
|
nsAutoString folderPath;
|
|
uriStr.Left(folderURI, keySeparator);
|
|
|
|
nsAutoString keyStr;
|
|
uriStr.Right(keyStr, uriStr.Length() - (keySeparator + 1));
|
|
PRInt32 errorCode;
|
|
*key = keyStr.ToInteger(&errorCode);
|
|
|
|
return errorCode;
|
|
}
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
nsresult nsBuildLocalMessageURI(const nsFileSpec& path, PRUint32 key, char** uri)
|
|
{
|
|
|
|
if(!uri)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
char *folderURI;
|
|
|
|
nsPath2URI(kMailboxMessageRootURI, path, &folderURI);
|
|
|
|
*uri = PR_smprintf("%s#%d", folderURI, key);
|
|
|
|
delete[] folderURI;
|
|
|
|
return NS_OK;
|
|
|
|
|
|
}
|
|
|
|
nsresult nsBuildNewsMessageURI(const nsFileSpec& path, PRUint32 key, char** uri)
|
|
{
|
|
|
|
if(!uri)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
char *folderURI;
|
|
|
|
nsPath2URI(kNewsMessageRootURI, path, &folderURI);
|
|
|
|
*uri = PR_smprintf("%s#%d", folderURI, key);
|
|
|
|
delete[] folderURI;
|
|
|
|
return NS_OK;
|
|
|
|
|
|
}
|
|
|
|
nsresult nsBuildImapMessageURI(const nsFileSpec& path, PRUint32 key, char** uri)
|
|
{
|
|
|
|
if(!uri)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
char *folderURI;
|
|
|
|
nsPath2URI(kImapMessageRootURI, path, &folderURI);
|
|
|
|
*uri = PR_smprintf("%s#%d", folderURI, key);
|
|
|
|
delete[] folderURI;
|
|
|
|
return NS_OK;
|
|
|
|
|
|
}
|
|
|
|
nsresult nsGetFolderFromMessage(nsIMessage *message, nsIMsgFolder** folder)
|
|
{
|
|
nsresult rv;
|
|
|
|
nsXPIDLCString uri;
|
|
nsIRDFResource *resource;
|
|
if(NS_SUCCEEDED( rv = message->QueryInterface(nsIRDFResource::GetIID(), (void**)&resource)))
|
|
{
|
|
resource->GetValue( getter_Copies(uri) );
|
|
nsString messageFolderURIStr;
|
|
nsMsgKey key;
|
|
nsParseMessageURI(uri, messageFolderURIStr, &key);
|
|
nsString folderOnly, folderURIStr;
|
|
|
|
if (messageFolderURIStr.Find(kMailboxMessageRootURI) != ((PRInt32)-1))
|
|
{
|
|
messageFolderURIStr.Right(folderOnly, messageFolderURIStr.Length() -nsCRT::strlen(kMailboxMessageRootURI));
|
|
folderURIStr = kMailboxRootURI;
|
|
folderURIStr+= folderOnly;
|
|
}
|
|
else if (messageFolderURIStr.Find(kNewsMessageRootURI) != ((PRInt32)-1))
|
|
{
|
|
messageFolderURIStr.Right(folderOnly, messageFolderURIStr.Length() -nsCRT::strlen(kNewsMessageRootURI));
|
|
folderURIStr = kMailboxRootURI;
|
|
folderURIStr+= folderOnly;
|
|
}
|
|
else if (messageFolderURIStr.Find(kImapMessageRootURI) != ((PRInt32)-1))
|
|
{
|
|
messageFolderURIStr.Right(folderOnly, messageFolderURIStr.Length() -nsCRT::strlen(kImapMessageRootURI));
|
|
folderURIStr = kMailboxRootURI;
|
|
folderURIStr+= folderOnly;
|
|
}
|
|
|
|
nsIRDFResource *folderResource;
|
|
char *folderURI = folderURIStr.ToNewCString();
|
|
|
|
|
|
nsIRDFService* rdfService;
|
|
nsresult rv = nsServiceManager::GetService(kRDFServiceCID,
|
|
nsIRDFService::GetIID(),
|
|
(nsISupports**) &rdfService);
|
|
if(NS_SUCCEEDED(rv))
|
|
{
|
|
rdfService->GetResource(folderURI, &folderResource);
|
|
nsServiceManager::ReleaseService(kRDFServiceCID, rdfService);
|
|
}
|
|
|
|
delete[] folderURI;
|
|
|
|
rv = NS_SUCCEEDED(folderResource->QueryInterface(nsIMsgFolder::GetIID(), (void**)folder));
|
|
|
|
NS_RELEASE(resource);
|
|
NS_RELEASE(folderResource);
|
|
}
|
|
return rv;
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|