more backend work for virtual folders, add support for pending db listeners, cleanup way db's are created and opened, r/sr=mscott 11051

This commit is contained in:
bienvenu%nventure.com 2004-08-02 15:43:12 +00:00
parent 73d09ce2c9
commit e2dc9c98b5
30 changed files with 1156 additions and 743 deletions

View File

@ -171,7 +171,7 @@ interface nsIMsgAccountManager : nsISupports {
void UnloadAccounts();
void WriteToFolderCache(in nsIMsgFolderCache folderCache);
void saveVirtualFolders();
void closeCachedConnections();
void shutdownServers();

View File

@ -20,6 +20,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* David Bienvenu <bienvenu@nventure.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -171,7 +172,7 @@ const nsMsgBiffState nsMsgBiffState_Unknown = 2; // We dunno whether there is ne
* @param name the new name of the folder
*/
void rename(in wstring name, in nsIMsgWindow msgWindow);
void renameSubFolders( in nsIMsgWindow msgWindow, in nsIMsgFolder oldFolder);
void renameSubFolders( in nsIMsgWindow msgWindow, in nsIMsgFolder oldFolder);
/**
* looks in immediate children of this folder for the given name
*

View File

@ -191,13 +191,13 @@ nsMsgSearchSession::AddScopeTerm(nsMsgSearchScopeValue scope,
nsIMsgFolder *folder)
{
if (scope != nsMsgSearchScope::allSearchableGroups)
{
NS_ASSERTION(folder, "need folder if not searching all groups");
if (!folder)
return NS_ERROR_NULL_POINTER;
}
{
NS_ASSERTION(folder, "need folder if not searching all groups");
if (!folder)
return NS_ERROR_NULL_POINTER;
}
nsMsgSearchScopeTerm *pScopeTerm = new nsMsgSearchScopeTerm(this, scope, folder);
nsMsgSearchScopeTerm *pScopeTerm = new nsMsgSearchScopeTerm(this, scope, folder);
if (!pScopeTerm)
return NS_ERROR_OUT_OF_MEMORY;
@ -727,6 +727,8 @@ nsMsgSearchSession::MatchHdr(nsIMsgDBHdr *aMsgHdr, nsIMsgDatabase *aDatabase, PR
nsMsgSearchScopeTerm *scope = (nsMsgSearchScopeTerm *)m_scopeList.SafeElementAt(0);
if (scope)
{
if (!scope->m_adapter)
scope->InitializeAdapter(m_termList);
if (scope->m_adapter)
{
nsXPIDLString nullCharset, folderCharset;

View File

@ -23,6 +23,7 @@
* Alec Flett <alecf@netscape.com>
* Seth Spitzer <sspitzer@netscape.com>
* Bhuvan Racham <racham@netscape.com>
* David Bienvenu <bienvenu@mozilla.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -48,6 +49,7 @@
#include "nsMsgAccountManager.h"
#include "nsMsgBaseCID.h"
#include "nsMsgCompCID.h"
#include "nsMsgDBCID.h"
#include "prmem.h"
#include "prcmon.h"
#include "prthread.h"
@ -60,6 +62,7 @@
#include "prprf.h"
#include "nsIMsgFolderCache.h"
#include "nsFileStream.h"
#include "nsIFileStreams.h"
#include "nsMsgUtils.h"
#include "nsIFileSpec.h"
#include "nsILocalFile.h"
@ -83,7 +86,14 @@
#include "nsIMessengerOSIntegration.h"
#include "nsICategoryManager.h"
#include "nsISupportsPrimitives.h"
#include "nsMsgFilterService.h"
#include "nsIMsgFilter.h"
#include "nsIMsgSearchSession.h"
#include "nsIDBChangeListener.h"
#include "nsIDBFolderInfo.h"
#include "nsIMsgHdr.h"
#include "nsILineInputStream.h"
#include "nsNetUtil.h"
#define PREF_MAIL_ACCOUNTMANAGER_ACCOUNTS "mail.accountmanager.accounts"
#define PREF_MAIL_ACCOUNTMANAGER_DEFAULTACCOUNT "mail.accountmanager.defaultaccount"
#define PREF_MAIL_ACCOUNTMANAGER_LOCALFOLDERSSERVER "mail.accountmanager.localfoldersserver"
@ -134,11 +144,12 @@ typedef struct _findAccountByKeyEntry {
} findAccountByKeyEntry;
NS_IMPL_THREADSAFE_ISUPPORTS4(nsMsgAccountManager,
NS_IMPL_THREADSAFE_ISUPPORTS5(nsMsgAccountManager,
nsIMsgAccountManager,
nsIObserver,
nsISupportsWeakReference,
nsIUrlListener)
nsIUrlListener,
nsIFolderListener)
nsMsgAccountManager::nsMsgAccountManager() :
m_accountsLoaded(PR_FALSE),
@ -157,12 +168,12 @@ nsMsgAccountManager::~nsMsgAccountManager()
if(!m_haveShutdown)
{
Shutdown();
//Don't remove from Observer service in Shutdown because Shutdown also gets called
//from xpcom shutdown observer. And we don't want to remove from the service in that case.
nsCOMPtr<nsIObserverService> observerService =
do_GetService("@mozilla.org/observer-service;1", &rv);
if (NS_SUCCEEDED(rv))
{
//Don't remove from Observer service in Shutdown because Shutdown also gets called
//from xpcom shutdown observer. And we don't want to remove from the service in that case.
nsCOMPtr<nsIObserverService> observerService =
do_GetService("@mozilla.org/observer-service;1", &rv);
if (NS_SUCCEEDED(rv))
{
observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
observerService->RemoveObserver(this, ABOUT_TO_GO_OFFLINE_TOPIC);
}
@ -194,17 +205,22 @@ nsresult nsMsgAccountManager::Init()
nsresult nsMsgAccountManager::Shutdown()
{
if (m_haveShutdown) {
// do not shutdown twice
if (m_haveShutdown) // do not shutdown twice
return NS_OK;
}
nsresult rv;
if(m_msgFolderCache)
SaveVirtualFolders();
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
if (msgDBService)
{
WriteToFolderCache(m_msgFolderCache);
PRInt32 numVFListeners = m_virtualFolderListeners.Count();
for(PRInt32 i = 0; i < numVFListeners; i++)
msgDBService->UnregisterPendingListener(m_virtualFolderListeners[i]);
}
if(m_msgFolderCache)
WriteToFolderCache(m_msgFolderCache);
(void)ShutdownServers();
(void)UnloadAccounts();
@ -946,7 +962,7 @@ nsMsgAccountManager::hashLogoutOfServer(nsHashKey *aKey, void *aData,
return PR_TRUE;
}
nsresult nsMsgAccountManager::GetFolderCache(nsIMsgFolderCache* *aFolderCache)
NS_IMETHODIMP nsMsgAccountManager::GetFolderCache(nsIMsgFolderCache* *aFolderCache)
{
if (!aFolderCache) return NS_ERROR_NULL_POINTER;
@ -1444,7 +1460,11 @@ nsMsgAccountManager::LoadAccounts()
}
LoadVirtualFolders();
nsCOMPtr<nsIMsgMailSession> mailSession = do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv))
mailSession->AddFolderListener(this, nsIFolderListener::added | nsIFolderListener::removed);
/* finished loading accounts */
return NS_OK;
}
@ -2391,4 +2411,435 @@ nsMsgAccountManager::GetChromePackageName(const char *aExtensionName, char **aCh
return NS_ERROR_UNEXPECTED;
}
class VirtualFolderChangeListener : public nsIDBChangeListener
{
public:
VirtualFolderChangeListener();
~VirtualFolderChangeListener() {};
NS_DECL_ISUPPORTS
NS_DECL_NSIDBCHANGELISTENER
nsresult Init();
nsCOMPtr <nsIMsgFolder> m_virtualFolder; // folder we're listening to db changes on behalf of.
nsCOMPtr <nsIMsgFolder> m_folderWatching; // folder whose db we're listening to.
nsCOMPtr <nsISupportsArray> m_searchTerms;
nsCOMPtr <nsIMsgSearchSession> m_searchSession;
PRBool m_searchOnMsgStatus;
};
NS_IMPL_ISUPPORTS1(VirtualFolderChangeListener, nsIDBChangeListener)
VirtualFolderChangeListener::VirtualFolderChangeListener() : m_searchOnMsgStatus(PR_FALSE)
{
}
nsresult VirtualFolderChangeListener::Init()
{
nsCOMPtr <nsIMsgDatabase> msgDB;
nsCOMPtr <nsIDBFolderInfo> dbFolderInfo;
nsresult rv = m_virtualFolder->GetDBFolderInfoAndDB(getter_AddRefs(dbFolderInfo), getter_AddRefs(msgDB));
if (NS_SUCCEEDED(rv) && msgDB)
{
nsXPIDLCString searchTermString;
dbFolderInfo->GetCharPtrProperty("searchStr", getter_Copies(searchTermString));
nsCOMPtr<nsIMsgFilterService> filterService = do_GetService(NS_MSGFILTERSERVICE_CONTRACTID, &rv);
nsCOMPtr<nsIMsgFilterList> filterList;
rv = filterService->GetTempFilterList(m_virtualFolder, getter_AddRefs(filterList));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr <nsIMsgFilter> tempFilter;
filterList->CreateFilter(NS_LITERAL_STRING("temp").get(), getter_AddRefs(tempFilter));
NS_ENSURE_SUCCESS(rv, rv);
filterList->ParseCondition(tempFilter, searchTermString);
NS_ENSURE_SUCCESS(rv, rv);
m_searchSession = do_CreateInstance(NS_MSGSEARCHSESSION_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupportsArray> searchTerms;
rv = tempFilter->GetSearchTerms(getter_AddRefs(searchTerms));
NS_ENSURE_SUCCESS(rv, rv);
m_searchSession->AddScopeTerm(nsMsgSearchScope::offlineMail, m_folderWatching);
// add each item in termsArray to the search session
PRUint32 numTerms;
searchTerms->Count(&numTerms);
for (PRUint32 i = 0; i < numTerms; i++)
{
nsCOMPtr <nsIMsgSearchTerm> searchTerm (do_QueryElementAt(searchTerms, i));
nsMsgSearchAttribValue attrib;
searchTerm->GetAttrib(&attrib);
if (attrib == nsMsgSearchAttrib::MsgStatus)
m_searchOnMsgStatus = true;
m_searchSession->AppendTerm(searchTerm);
}
}
return rv;
}
/**
* nsIDBChangeListener
*/
NS_IMETHODIMP VirtualFolderChangeListener::OnKeyChange(nsMsgKey aKeyChanged, PRUint32 aOldFlags, PRUint32 aNewFlags, nsIDBChangeListener *aInstigator)
{
nsCOMPtr <nsIMsgDatabase> msgDB;
nsresult rv = m_folderWatching->GetMsgDatabase(nsnull, getter_AddRefs(msgDB));
nsCOMPtr <nsIMsgDBHdr> msgHdr;
rv = msgDB->GetMsgHdrForKey(aKeyChanged, getter_AddRefs(msgHdr));
NS_ENSURE_SUCCESS(rv, rv);
PRBool oldMatch = PR_FALSE, newMatch = PR_FALSE;
rv = m_searchSession->MatchHdr(msgHdr, msgDB, &newMatch);
NS_ENSURE_SUCCESS(rv, rv);
if (m_searchOnMsgStatus)
{
// if status is a search criteria, check if the header matched before
// it changed, in order to determine if we need to bump the counts.
msgHdr->SetFlags(aOldFlags);
rv = m_searchSession->MatchHdr(msgHdr, msgDB, &oldMatch);
msgHdr->SetFlags(aNewFlags); // restore new flags even on match failure.
NS_ENSURE_SUCCESS(rv, rv);
}
else
oldMatch = newMatch;
// we don't want to change the total counts if this virtual folder is open in a view,
// because we won't remove the header from view while its open.
if (oldMatch != newMatch || (oldMatch && (aOldFlags & MSG_FLAG_READ) != (aNewFlags & MSG_FLAG_READ)))
{
nsCOMPtr <nsIMsgDatabase> virtDatabase;
nsCOMPtr <nsIDBFolderInfo> dbFolderInfo;
rv = m_virtualFolder->GetDBFolderInfoAndDB(getter_AddRefs(dbFolderInfo), getter_AddRefs(virtDatabase));
PRInt32 totalDelta = 0, unreadDelta = 0;
if (oldMatch != newMatch)
totalDelta = (oldMatch) ? -1 : 1;
PRBool msgHdrIsRead;
msgHdr->GetIsRead(&msgHdrIsRead);
if (oldMatch == newMatch) // read flag changed state
unreadDelta = (msgHdrIsRead) ? -1 : 1;
else if (oldMatch) // else header should removed
unreadDelta = (aOldFlags & MSG_FLAG_READ) ? 0 : -1;
else // header should be added
unreadDelta = (aNewFlags & MSG_FLAG_READ) ? 0 : 1;
if (unreadDelta)
dbFolderInfo->ChangeNumUnreadMessages(unreadDelta);
if (totalDelta)
dbFolderInfo->ChangeNumMessages(totalDelta);
m_virtualFolder->UpdateSummaryTotals(PR_TRUE); // force update from db.
virtDatabase->Commit(nsMsgDBCommitType::kLargeCommit);
}
return rv;
}
NS_IMETHODIMP VirtualFolderChangeListener::OnKeyDeleted(nsMsgKey aKeyDeleted, nsMsgKey aParentKey, PRInt32 aFlags, nsIDBChangeListener *aInstigator)
{
nsCOMPtr <nsIMsgDatabase> msgDB;
nsresult rv = m_folderWatching->GetMsgDatabase(nsnull, getter_AddRefs(msgDB));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr <nsIMsgDBHdr> msgHdr;
rv = msgDB->GetMsgHdrForKey(aKeyDeleted, getter_AddRefs(msgHdr));
NS_ENSURE_SUCCESS(rv, rv);
PRBool match = PR_FALSE;
rv = m_searchSession->MatchHdr(msgHdr, msgDB, &match);
if (match)
{
nsCOMPtr <nsIMsgDatabase> virtDatabase;
nsCOMPtr <nsIDBFolderInfo> dbFolderInfo;
nsresult rv = m_virtualFolder->GetDBFolderInfoAndDB(getter_AddRefs(dbFolderInfo), getter_AddRefs(virtDatabase));
PRBool msgHdrIsRead;
msgHdr->GetIsRead(&msgHdrIsRead);
if (!msgHdrIsRead)
dbFolderInfo->ChangeNumUnreadMessages(-1);
dbFolderInfo->ChangeNumMessages(-1);
m_virtualFolder->UpdateSummaryTotals(PR_TRUE); // force update from db.
virtDatabase->Commit(nsMsgDBCommitType::kLargeCommit);
}
return rv;
}
NS_IMETHODIMP VirtualFolderChangeListener::OnKeyAdded(nsMsgKey aNewKey, nsMsgKey aParentKey, PRInt32 aFlags, nsIDBChangeListener *aInstigator)
{
nsCOMPtr <nsIMsgDatabase> msgDB;
nsresult rv = m_folderWatching->GetMsgDatabase(nsnull, getter_AddRefs(msgDB));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr <nsIMsgDBHdr> msgHdr;
rv = msgDB->GetMsgHdrForKey(aNewKey, getter_AddRefs(msgHdr));
NS_ENSURE_SUCCESS(rv, rv);
PRBool match = PR_FALSE;
rv = m_searchSession->MatchHdr(msgHdr, msgDB, &match);
if (match)
{
nsCOMPtr <nsIMsgDatabase> virtDatabase;
nsCOMPtr <nsIDBFolderInfo> dbFolderInfo;
rv = m_virtualFolder->GetDBFolderInfoAndDB(getter_AddRefs(dbFolderInfo), getter_AddRefs(virtDatabase));
PRBool msgHdrIsRead;
msgHdr->GetIsRead(&msgHdrIsRead);
if (!msgHdrIsRead)
dbFolderInfo->ChangeNumUnreadMessages(1);
dbFolderInfo->ChangeNumMessages(1);
m_virtualFolder->UpdateSummaryTotals(true); // force update from db.
virtDatabase->Commit(nsMsgDBCommitType::kLargeCommit);
}
return rv;
}
NS_IMETHODIMP VirtualFolderChangeListener::OnParentChanged(nsMsgKey aKeyChanged, nsMsgKey oldParent, nsMsgKey newParent, nsIDBChangeListener *aInstigator)
{
return NS_OK;
}
NS_IMETHODIMP VirtualFolderChangeListener::OnAnnouncerGoingAway(nsIDBChangeAnnouncer *instigator)
{
nsresult rv;
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
if (msgDBService)
msgDBService->UnregisterPendingListener(this);
return rv;
}
NS_IMETHODIMP VirtualFolderChangeListener::OnReadChanged(nsIDBChangeListener *aInstigator)
{
return NS_OK;
}
NS_IMETHODIMP VirtualFolderChangeListener::OnJunkScoreChanged(nsIDBChangeListener *aInstigator)
{
return NS_OK;
}
nsresult nsMsgAccountManager::GetVirtualFoldersFile(nsCOMPtr<nsILocalFile>& file)
{
nsCOMPtr<nsIFile> profileDir;
nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(profileDir));
NS_ENSURE_SUCCESS(rv, rv);
rv = profileDir->AppendNative(nsDependentCString("virtualFolders.dat"));
if (NS_SUCCEEDED(rv))
file = do_QueryInterface(profileDir, &rv);
return rv;
}
nsresult nsMsgAccountManager::LoadVirtualFolders()
{
nsCOMPtr <nsILocalFile> file;
GetVirtualFoldersFile(file);
if (!file)
return NS_ERROR_FAILURE;
nsresult rv;
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
if (msgDBService)
{
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFileInputStream> fileStream = do_CreateInstance(NS_LOCALFILEINPUTSTREAM_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = fileStream->Init(file, PR_RDONLY, 0664, PR_FALSE); //just have to read the messages
nsCOMPtr <nsILineInputStream> lineInputStream(do_QueryInterface(fileStream));
PRBool isMore = PR_TRUE;
nsCAutoString buffer;
while (isMore &&
NS_SUCCEEDED(lineInputStream->ReadLine(buffer, &isMore)))
{
if (buffer.Length() > 0)
{
nsCOMPtr <nsIMsgFolder> folder;
nsCOMPtr<nsIRDFService> rdf(do_GetService("@mozilla.org/rdf/rdf-service;1", &rv));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIRDFResource> resource;
rv = rdf->GetResource(buffer, getter_AddRefs(resource));
NS_ENSURE_SUCCESS(rv, rv);
folder = do_QueryInterface(resource, &rv);
NS_ENSURE_SUCCESS(rv, rv);
if (folder)
{
// need to add the folder as a sub-folder of its parent.
PRInt32 lastSlash = buffer.RFindChar('/');
nsDependentCSubstring parentUri(buffer, 0, lastSlash);
rdf->GetResource(parentUri, getter_AddRefs(resource));
nsCOMPtr <nsIMsgFolder> parentFolder = do_QueryInterface(resource);
if (parentFolder)
{
nsCOMPtr <nsIMsgFolder> childFolder;
nsAutoString currentFolderNameStr;
CopyUTF8toUTF16(Substring(buffer, lastSlash + 1, buffer.Length()), currentFolderNameStr);
rv = parentFolder->AddSubfolder(currentFolderNameStr, getter_AddRefs(childFolder));
if (!childFolder)
childFolder = folder; // or just use folder?
nsCOMPtr <nsIMsgDatabase> db;
childFolder->GetMsgDatabase(nsnull, getter_AddRefs(db)); // force db to get created.
nsCOMPtr <nsIDBFolderInfo> dbFolderInfo;
rv = db->GetDBFolderInfo(getter_AddRefs(dbFolderInfo));
childFolder->SetFlag(MSG_FOLDER_FLAG_VIRTUAL);
nsXPIDLCString realFolderUri;
dbFolderInfo->GetCharPtrProperty("searchFolderUri", getter_Copies(realFolderUri));
// if we supported cross folder virtual folders, we'd have a list of folders uris,
// and we'd have to add a pending listener for each of them.
if (realFolderUri.Length())
{
// we need to load the db for the actual folder so that many hdrs to download
// will return false...
rdf->GetResource(realFolderUri, getter_AddRefs(resource));
nsCOMPtr <nsIMsgFolder> realFolder = do_QueryInterface(resource);
VirtualFolderChangeListener *dbListener = new VirtualFolderChangeListener();
m_virtualFolderListeners.AppendObject(dbListener);
dbListener->m_virtualFolder = childFolder;
dbListener->m_folderWatching = realFolder;
dbListener->Init();
msgDBService->RegisterPendingListener(realFolder, dbListener);
}
}
}
}
}
}
return rv;
}
NS_IMETHODIMP nsMsgAccountManager::SaveVirtualFolders()
{
nsCOMPtr<nsISupportsArray> allServers;
nsresult rv = GetAllServers(getter_AddRefs(allServers));
nsCOMPtr <nsILocalFile> file;
if (allServers)
{
PRUint32 count = 0;
allServers->Count(&count);
PRInt32 i;
nsCOMPtr <nsIOutputStream> outputStream;
for (i = 0; i < count; i++)
{
nsCOMPtr<nsIMsgIncomingServer> server = do_QueryElementAt(allServers, i);
if (server)
{
nsCOMPtr <nsIMsgFolder> rootFolder;
server->GetRootFolder(getter_AddRefs(rootFolder));
if (rootFolder)
{
nsCOMPtr <nsISupportsArray> virtualFolders;
rv = rootFolder->GetAllFoldersWithFlag(MSG_FOLDER_FLAG_VIRTUAL, getter_AddRefs(virtualFolders));
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 vfCount;
virtualFolders->Count(&vfCount);
for (PRInt32 folderIndex = 0; folderIndex < vfCount; folderIndex++)
{
if (!outputStream)
{
GetVirtualFoldersFile(file);
rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream),
file,
PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE,
0664);
}
nsCOMPtr <nsIRDFResource> folderRes (do_QueryElementAt(virtualFolders, folderIndex));
const char *uri;
folderRes->GetValueConst(&uri);
PRUint32 writeCount;
outputStream->Write(uri, strlen(uri), &writeCount);
outputStream->Write("\n", 1, &writeCount);
}
}
}
}
if (outputStream)
outputStream->Close();
}
return rv;
}
NS_IMETHODIMP nsMsgAccountManager::OnItemAdded(nsIRDFResource *parentItem, nsISupports *item)
{
nsCOMPtr<nsIMsgFolder> folder = do_QueryInterface(item);
NS_ENSURE_TRUE(folder, NS_OK); // just kick out with a success code if the item in question is not a folder
PRUint32 folderFlags;
folder->GetFlags(&folderFlags);
nsresult rv = NS_OK;
// need to make sure this isn't happening during loading of virtualfolders.dat
if (folderFlags & MSG_FOLDER_FLAG_VIRTUAL)
{
// When a new virtual folder is added, need to create a db Listener for it.
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
if (msgDBService)
{
VirtualFolderChangeListener *dbListener = new VirtualFolderChangeListener();
dbListener->m_virtualFolder = folder;
nsCOMPtr <nsIMsgDatabase> virtDatabase;
nsCOMPtr <nsIDBFolderInfo> dbFolderInfo;
m_virtualFolderListeners.AppendObject(dbListener);
rv = folder->GetDBFolderInfoAndDB(getter_AddRefs(dbFolderInfo), getter_AddRefs(virtDatabase));
NS_ENSURE_SUCCESS(rv, rv);
nsXPIDLCString srchFolderUri;
dbFolderInfo->GetCharPtrProperty("searchFolderUri", getter_Copies(srchFolderUri));
// if we supported cross folder virtual folders, we'd have a list of folders uris,
// and we'd have to add a pending listener for each of them.
rv = GetExistingFolder(srchFolderUri.get(), getter_AddRefs(dbListener->m_folderWatching));
if (dbListener->m_folderWatching)
msgDBService->RegisterPendingListener(dbListener->m_folderWatching, dbListener);
}
rv = SaveVirtualFolders();
}
return rv;
}
NS_IMETHODIMP nsMsgAccountManager::OnItemRemoved(nsIRDFResource *parentItem, nsISupports *item)
{
nsCOMPtr<nsIMsgFolder> folder = do_QueryInterface(item);
NS_ENSURE_TRUE(folder, NS_OK); // just kick out with a success code if the item in question is not a folder
nsresult rv = NS_OK;
PRUint32 folderFlags;
folder->GetFlags(&folderFlags);
if (folderFlags & MSG_FOLDER_FLAG_VIRTUAL) // if we removed a VF, flush VF list to disk.
rv = SaveVirtualFolders();
// need to check if the underlying folder for a VF was removed, in which case we need to
// remove the virtual folder.
return rv;
}
NS_IMETHODIMP nsMsgAccountManager::OnItemPropertyChanged(nsIRDFResource *item, nsIAtom *property, const char *oldValue, const char *newValue)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsMsgAccountManager::OnItemIntPropertyChanged(nsIRDFResource *item, nsIAtom *property, PRInt32 oldValue, PRInt32 newValue)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsMsgAccountManager::OnItemBoolPropertyChanged(nsIRDFResource *item, nsIAtom *property, PRBool oldValue, PRBool newValue)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsMsgAccountManager::OnItemUnicharPropertyChanged(nsIRDFResource *item, nsIAtom *property, const PRUnichar *oldValue, const PRUnichar *newValue)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsMsgAccountManager::OnItemPropertyFlagChanged(nsISupports *item, nsIAtom *property, PRUint32 oldFlag, PRUint32 newFlag)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsMsgAccountManager::OnItemEvent(nsIMsgFolder *aFolder, nsIAtom *aEvent)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@ -56,11 +56,11 @@
#include "nsIUrlListener.h"
#include "nsCOMArray.h"
class nsMsgAccountManager
: public nsIMsgAccountManager,
public nsIObserver,
public nsSupportsWeakReference,
public nsIUrlListener
class nsMsgAccountManager: public nsIMsgAccountManager,
public nsIObserver,
public nsSupportsWeakReference,
public nsIUrlListener,
public nsIFolderListener
{
public:
@ -74,6 +74,7 @@ public:
NS_DECL_NSIMSGACCOUNTMANAGER
NS_DECL_NSIOBSERVER
NS_DECL_NSIURLLISTENER
NS_DECL_NSIFOLDERLISTENER
nsresult Init();
nsresult Shutdown();
@ -89,6 +90,7 @@ private:
nsHashtable m_incomingServers;
nsCOMPtr<nsIMsgAccount> m_defaultAccount;
nsCOMArray<nsIIncomingServerListener> m_incomingServerListeners;
nsCOMArray<nsIDBChangeListener> m_virtualFolderListeners;
nsCOMPtr<nsIMsgFolder> m_folderDoingEmptyTrash;
nsCOMPtr<nsIMsgFolder> m_folderDoingCleanupInbox;
PRBool m_emptyTrashInProgress;
@ -195,6 +197,10 @@ private:
static PRBool PR_CALLBACK shutdown(nsHashKey *aKey, void *aData, void *closure);
static PRBool PR_CALLBACK closeCachedConnections(nsHashKey *aKey, void *aData, void *closure);
// handle virtual folders
nsresult GetVirtualFoldersFile(nsCOMPtr<nsILocalFile>& file);
nsresult LoadVirtualFolders();
static void getUniqueKey(const char* prefix,
nsHashtable *hashTable,
nsCString& aResult);

View File

@ -130,15 +130,13 @@ nsFolderCompactState::InitDB(nsIMsgDatabase *db)
nsCOMPtr<nsIMsgDatabase> mailDBFactory;
nsCOMPtr<nsIFileSpec> newPathSpec;
db ->ListAllKeys(m_keyArray);
db->ListAllKeys(m_keyArray);
nsresult rv = NS_NewFileSpecWithSpec(m_fileSpec, getter_AddRefs(newPathSpec));
rv = nsComponentManager::CreateInstance(kCMailDB, nsnull,
NS_GET_IID(nsIMsgDatabase),
getter_AddRefs(mailDBFactory));
if (NS_SUCCEEDED(rv))
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
if (msgDBService)
{
nsresult folderOpen = mailDBFactory->Open(newPathSpec, PR_TRUE,
nsresult folderOpen = msgDBService->OpenMailDBFromFileSpec(newPathSpec, PR_TRUE,
PR_FALSE,
getter_AddRefs(m_db));
@ -147,7 +145,7 @@ nsFolderCompactState::InitDB(nsIMsgDatabase *db)
folderOpen == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING )
{
// if it's out of date then reopen with upgrade.
rv = mailDBFactory->Open(newPathSpec,
rv = msgDBService->OpenMailDBFromFileSpec(newPathSpec,
PR_TRUE, PR_TRUE,
getter_AddRefs(m_db));
}
@ -321,7 +319,7 @@ nsFolderCompactState::Init(nsIMsgFolder *folder, const char *baseMsgUri, nsIMsgD
}
void nsFolderCompactState::ShowCompactingStatusMsg()
{
{
nsXPIDLString statusString;
nsresult rv = m_folder->GetStringWithFolderNameFromBundle("compactingFolder", getter_Copies(statusString));
if (statusString && NS_SUCCEEDED(rv))

View File

@ -97,6 +97,7 @@ nsIRDFResource* nsMsgFolderDataSource::kNC_HasUnreadMessages = nsnull;
nsIRDFResource* nsMsgFolderDataSource::kNC_NewMessages = nsnull;
nsIRDFResource* nsMsgFolderDataSource::kNC_SubfoldersHaveUnreadMessages = nsnull;
nsIRDFResource* nsMsgFolderDataSource::kNC_NoSelect = nsnull;
nsIRDFResource* nsMsgFolderDataSource::kNC_VirtualFolder = nsnull;
nsIRDFResource* nsMsgFolderDataSource::kNC_ImapShared = nsnull;
nsIRDFResource* nsMsgFolderDataSource::kNC_Synchronize = nsnull;
nsIRDFResource* nsMsgFolderDataSource::kNC_SyncDisabled = nsnull;
@ -170,6 +171,7 @@ nsMsgFolderDataSource::nsMsgFolderDataSource()
rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_NEWMESSAGES), &kNC_NewMessages);
rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_SUBFOLDERSHAVEUNREADMESSAGES), &kNC_SubfoldersHaveUnreadMessages);
rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_NOSELECT), &kNC_NoSelect);
rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_VIRTUALFOLDER), &kNC_VirtualFolder);
rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_IMAPSHARED), &kNC_ImapShared);
rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_SYNCHRONIZE), &kNC_Synchronize);
rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_SYNCDISABLED), &kNC_SyncDisabled);
@ -243,6 +245,7 @@ nsMsgFolderDataSource::~nsMsgFolderDataSource (void)
NS_RELEASE2(kNC_NewMessages, refcnt);
NS_RELEASE2(kNC_SubfoldersHaveUnreadMessages, refcnt);
NS_RELEASE2(kNC_NoSelect, refcnt);
NS_RELEASE2(kNC_VirtualFolder, refcnt);
NS_RELEASE2(kNC_ImapShared, refcnt);
NS_RELEASE2(kNC_Synchronize, refcnt);
NS_RELEASE2(kNC_SyncDisabled, refcnt);
@ -477,6 +480,7 @@ NS_IMETHODIMP nsMsgFolderDataSource::GetTargets(nsIRDFResource* source,
(kNC_CanCreateFoldersOnServer == property) ||
(kNC_CanFileMessagesOnServer == property) ||
(kNC_NoSelect == property) ||
(kNC_VirtualFolder == property) ||
(kNC_ImapShared == property) ||
(kNC_Synchronize == property) ||
(kNC_SyncDisabled == property) ||
@ -583,6 +587,7 @@ nsMsgFolderDataSource::HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc,
aArc == kNC_BiffState ||
aArc == kNC_Child ||
aArc == kNC_NoSelect ||
aArc == kNC_VirtualFolder ||
aArc == kNC_ImapShared ||
aArc == kNC_Synchronize ||
aArc == kNC_SyncDisabled ||
@ -654,6 +659,7 @@ nsMsgFolderDataSource::getFolderArcLabelsOut(nsISupportsArray **arcs)
(*arcs)->AppendElement(kNC_BiffState);
(*arcs)->AppendElement(kNC_Child);
(*arcs)->AppendElement(kNC_NoSelect);
(*arcs)->AppendElement(kNC_VirtualFolder);
(*arcs)->AppendElement(kNC_ImapShared);
(*arcs)->AppendElement(kNC_Synchronize);
(*arcs)->AppendElement(kNC_SyncDisabled);
@ -1036,6 +1042,8 @@ nsresult nsMsgFolderDataSource::createFolderNode(nsIMsgFolder* folder,
rv = createFolderChildNode(folder, target);
else if ((kNC_NoSelect == property))
rv = createFolderNoSelectNode(folder, target);
else if ((kNC_VirtualFolder == property))
rv = createFolderVirtualNode(folder, target);
else if ((kNC_ImapShared == property))
rv = createFolderImapSharedNode(folder, target);
else if ((kNC_Synchronize == property))
@ -1284,6 +1292,19 @@ nsMsgFolderDataSource::createFolderNoSelectNode(nsIMsgFolder* folder,
return NS_OK;
}
nsresult
nsMsgFolderDataSource::createFolderVirtualNode(nsIMsgFolder* folder,
nsIRDFNode **target)
{
PRUint32 folderFlags;
folder->GetFlags(&folderFlags);
*target = (folderFlags & MSG_FOLDER_FLAG_VIRTUAL) ? kTrueLiteral : kFalseLiteral;
NS_IF_ADDREF(*target);
return NS_OK;
}
nsresult
nsMsgFolderDataSource::createFolderImapSharedNode(nsIMsgFolder* folder,
nsIRDFNode **target)

View File

@ -165,6 +165,8 @@ protected:
nsresult createNewMessagesNode(nsIMsgFolder *folder, nsIRDFNode **target);
nsresult createFolderNoSelectNode(nsIMsgFolder *folder,
nsIRDFNode **target);
nsresult createFolderVirtualNode(nsIMsgFolder *folder,
nsIRDFNode **target);
nsresult createFolderImapSharedNode(nsIMsgFolder *folder,
nsIRDFNode **target);
nsresult createFolderSynchronizeNode(nsIMsgFolder *folder, nsIRDFNode **target);
@ -191,12 +193,12 @@ protected:
nsresult DoFolderUnassert(nsIMsgFolder *folder, nsIRDFResource *property, nsIRDFNode *target);
nsresult DoFolderHasAssertion(nsIMsgFolder *folder, nsIRDFResource *property, nsIRDFNode *target,
PRBool tv, PRBool *hasAssertion);
PRBool tv, PRBool *hasAssertion);
nsresult GetBiffStateString(PRUint32 biffState, nsCAutoString & biffStateStr);
nsresult GetBiffStateString(PRUint32 biffState, nsCAutoString & biffStateStr);
nsresult CreateUnreadMessagesNameString(PRInt32 unreadMessages, nsAutoString &nameString);
nsresult CreateArcsOutEnumerator();
nsresult CreateUnreadMessagesNameString(PRInt32 unreadMessages, nsAutoString &nameString);
nsresult CreateArcsOutEnumerator();
nsresult OnItemAddedOrRemoved(nsIRDFResource *parentItem, nsISupports *item, PRBool added);
@ -248,6 +250,7 @@ protected:
static nsIRDFResource* kNC_Synchronize;
static nsIRDFResource* kNC_SyncDisabled;
static nsIRDFResource* kNC_CanSearchMessages;
static nsIRDFResource* kNC_VirtualFolder;
// commands

View File

@ -58,23 +58,23 @@ class nsMsgMailSession : public nsIMsgMailSession,
public nsIFolderListener
{
public:
nsMsgMailSession();
virtual ~nsMsgMailSession();
nsMsgMailSession();
virtual ~nsMsgMailSession();
NS_DECL_ISUPPORTS
NS_DECL_NSIMSGMAILSESSION
NS_DECL_NSIFOLDERLISTENER
NS_DECL_ISUPPORTS
NS_DECL_NSIMSGMAILSESSION
NS_DECL_NSIFOLDERLISTENER
nsresult Init();
nsresult GetSelectedLocaleDataDir(nsIFile *defaultsDir);
nsresult Init();
nsresult GetSelectedLocaleDataDir(nsIFile *defaultsDir);
protected:
nsCOMArray<nsIFolderListener> mListeners;
nsUInt32Array mListenerNotifyFlags;
nsCOMPtr<nsISupportsArray> mWindows;
// stick this here temporarily
nsCOMPtr <nsIMsgWindow> m_temporaryMsgWindow;
nsCOMPtr<nsISupportsArray> mWindows;
// stick this here temporarily
nsCOMPtr <nsIMsgWindow> m_temporaryMsgWindow;
};

View File

@ -82,6 +82,7 @@ typedef struct _nsMsgRDFNotification {
#define NC_RDF_HASUNREADMESSAGES NC_NAMESPACE_URI "HasUnreadMessages"
#define NC_RDF_SUBFOLDERSHAVEUNREADMESSAGES NC_NAMESPACE_URI "SubfoldersHaveUnreadMessages"
#define NC_RDF_NOSELECT NC_NAMESPACE_URI "NoSelect"
#define NC_RDF_VIRTUALFOLDER NC_NAMESPACE_URI "Virtual"
#define NC_RDF_IMAPSHARED NC_NAMESPACE_URI "ImapShared"
#define NC_RDF_NEWMESSAGES NC_NAMESPACE_URI "NewMessages"
#define NC_RDF_SYNCHRONIZE NC_NAMESPACE_URI "Synchronize"

View File

@ -201,38 +201,38 @@ nsMsgDBFolder::~nsMsgDBFolder(void)
#endif
}
//shutdown but don't shutdown children.
Shutdown(PR_FALSE);
Shutdown(PR_FALSE);
}
NS_IMETHODIMP nsMsgDBFolder::Shutdown(PRBool shutdownChildren)
{
if(mDatabase)
{
mDatabase->RemoveListener(this);
mDatabase->Close(PR_TRUE);
mDatabase = nsnull;
if(mDatabase)
{
mDatabase->RemoveListener(this);
mDatabase->Close(PR_TRUE);
mDatabase = nsnull;
}
if(shutdownChildren)
{
PRUint32 count;
nsresult rv = mSubFolders->Count(&count);
if(NS_SUCCEEDED(rv))
{
for (PRUint32 i = 0; i < count; i++)
{
nsCOMPtr<nsIMsgFolder> childFolder = do_QueryElementAt(mSubFolders, i);
if(childFolder)
childFolder->Shutdown(PR_TRUE);
}
}
if(shutdownChildren)
{
PRUint32 count;
nsresult rv = mSubFolders->Count(&count);
if(NS_SUCCEEDED(rv))
{
for (PRUint32 i = 0; i < count; i++)
{
nsCOMPtr<nsIMsgFolder> childFolder = do_QueryElementAt(mSubFolders, i);
if(childFolder)
childFolder->Shutdown(PR_TRUE);
}
}
// Reset incoming server pointer and pathname.
mServer = nsnull;
mPath = nsnull;
mSubFolders->Clear();
}
return NS_OK;
}
return NS_OK;
}
@ -2979,8 +2979,8 @@ NS_IMETHODIMP nsMsgDBFolder::RecursiveDelete(PRBool deleteStorage, nsIMsgWindow
}
// now delete the disk storage for _this_
if (deleteStorage && (status == NS_OK))
status = Delete();
if (deleteStorage && (status == NS_OK))
status = Delete();
return status;
}
@ -3237,8 +3237,13 @@ NS_IMETHODIMP nsMsgDBFolder::GetNumUnread(PRBool deep, PRInt32 *numUnread)
if (NS_SUCCEEDED(rv))
{
PRInt32 num;
folder->GetNumUnread(deep, &num);
total += num;
PRUint32 folderFlags;
folder->GetFlags(&folderFlags);
if (!(folderFlags & MSG_FOLDER_FLAG_VIRTUAL))
{
folder->GetNumUnread(deep, &num);
total += num;
}
}
}
}
@ -3269,8 +3274,13 @@ NS_IMETHODIMP nsMsgDBFolder::GetTotalMessages(PRBool deep, PRInt32 *totalMessage
if (NS_SUCCEEDED(rv))
{
PRInt32 num;
folder->GetTotalMessages (deep, &num);
total += num;
PRUint32 folderFlags;
folder->GetFlags(&folderFlags);
if (!(folderFlags & MSG_FOLDER_FLAG_VIRTUAL))
{
folder->GetTotalMessages (deep, &num);
total += num;
}
}
}
}

View File

@ -70,35 +70,35 @@
class NS_MSG_BASE nsMsgMailNewsUrl : public nsIMsgMailNewsUrl
{
public:
nsMsgMailNewsUrl();
nsMsgMailNewsUrl();
NS_DECL_ISUPPORTS
NS_DECL_ISUPPORTS
NS_DECL_NSIMSGMAILNEWSURL
NS_DECL_NSIURI
NS_DECL_NSIURL
protected:
virtual ~nsMsgMailNewsUrl();
virtual ~nsMsgMailNewsUrl();
// a helper function I needed from derived urls...
virtual const char * GetUserName() = 0;
// a helper function I needed from derived urls...
virtual const char * GetUserName() = 0;
nsCOMPtr<nsIURL> m_baseURL;
nsCOMPtr<nsIMsgStatusFeedback> m_statusFeedback;
nsCOMPtr<nsIMsgWindow> m_msgWindow;
nsCOMPtr<nsILoadGroup> m_loadGroup;
nsCOMPtr<nsIURL> m_baseURL;
nsCOMPtr<nsIMsgStatusFeedback> m_statusFeedback;
nsCOMPtr<nsIMsgWindow> m_msgWindow;
nsCOMPtr<nsILoadGroup> m_loadGroup;
nsCOMPtr<nsIMimeHeaders> mMimeHeaders;
nsCOMPtr<nsIMsgSearchSession> m_searchSession;
nsCOMPtr<nsICacheEntryDescriptor> m_memCacheEntry;
nsCOMPtr<nsICacheSession> m_imageCacheSession;
nsCOMPtr<nsISupportsArray> m_cachedMemCacheEntries;
nsCOMPtr<nsIMsgHeaderSink> mMsgHeaderSink;
char *m_errorMessage;
PRBool m_runningUrl;
PRBool m_updatingFolder;
PRBool m_addContentToCache;
PRBool m_msgIsInLocalCache;
PRBool m_suppressErrorMsgs;
char *m_errorMessage;
PRBool m_runningUrl;
PRBool m_updatingFolder;
PRBool m_addContentToCache;
PRBool m_msgIsInLocalCache;
PRBool m_suppressErrorMsgs;
// the following field is really a bit of a hack to make
// open attachments work. The external applications code sometimes trys to figure out the right
@ -108,8 +108,8 @@ protected:
// asks us for it, we'll return the right value.
nsCString mAttachmentFileName;
// manager of all of current url listeners....
nsCOMPtr<nsIUrlListenerManager> m_urlListeners;
// manager of all of current url listeners....
nsCOMPtr<nsIUrlListenerManager> m_urlListeners;
};
#undef IMETHOD_VISIBILITY

View File

@ -682,7 +682,7 @@ NS_IMETHODIMP nsMsgComposeService::InitCompose(nsIDOMWindowInternal *aWindow,
#endif
NS_IF_ADDREF(*_retval = msgCompose);
return rv;
return rv;
}
NS_IMETHODIMP

View File

@ -52,6 +52,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsNewsDatabase)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsImapMailDatabase)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgRetentionSettings)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgDownloadSettings)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgDBService)
// The list of components we register
static const nsModuleComponentInfo msgDB_components[] = {
@ -61,7 +62,8 @@ static const nsModuleComponentInfo msgDB_components[] = {
{ "Msg Retention Settings", NS_MSG_RETENTIONSETTINGS_CID,
NS_MSG_RETENTIONSETTINGS_CONTRACTID, nsMsgRetentionSettingsConstructor },
{ "Msg Download Settings", NS_MSG_DOWNLOADSETTINGS_CID,
NS_MSG_DOWNLOADSETTINGS_CONTRACTID, nsMsgDownloadSettingsConstructor }
NS_MSG_DOWNLOADSETTINGS_CONTRACTID, nsMsgDownloadSettingsConstructor },
{ "Msg DB Service" NS_MSGDB_SERVICE_CID, NS_MSGDB_SERVICE_CONTRACTID, nsMsgDBServiceConstructor }
};
PR_STATIC_CALLBACK(void)

View File

@ -43,16 +43,16 @@ interface nsIDBChangeAnnouncer;
[scriptable, uuid(ad0f7f90-baff-11d2-8d67-00805f8a6617)]
interface nsIDBChangeListener : nsISupports {
void OnKeyChange(in nsMsgKey aKeyChanged, in unsigned long aOldFlags, in unsigned long aNewFlags,
void onKeyChange(in nsMsgKey aKeyChanged, in unsigned long aOldFlags, in unsigned long aNewFlags,
in nsIDBChangeListener aInstigator);
void OnKeyDeleted(in nsMsgKey aKeyChanged, in nsMsgKey aParentKey, in long aFlags,
void onKeyDeleted(in nsMsgKey aKeyChanged, in nsMsgKey aParentKey, in long aFlags,
in nsIDBChangeListener aInstigator);
void OnKeyAdded(in nsMsgKey aKeyChanged, in nsMsgKey aParentKey, in long aFlags,
void onKeyAdded(in nsMsgKey aKeyChanged, in nsMsgKey aParentKey, in long aFlags,
in nsIDBChangeListener aInstigator);
void OnParentChanged (in nsMsgKey aKeyChanged, in nsMsgKey oldParent, in nsMsgKey newParent, in nsIDBChangeListener aInstigator);
void OnAnnouncerGoingAway(in nsIDBChangeAnnouncer instigator);
void onParentChanged (in nsMsgKey aKeyChanged, in nsMsgKey oldParent, in nsMsgKey newParent, in nsIDBChangeListener aInstigator);
void onAnnouncerGoingAway(in nsIDBChangeAnnouncer instigator);
void OnReadChanged(in nsIDBChangeListener aInstigator);
void OnJunkScoreChanged(in nsIDBChangeListener aInstigator);
void onReadChanged(in nsIDBChangeListener aInstigator);
void onJunkScoreChanged(in nsIDBChangeListener aInstigator);
};

View File

@ -105,11 +105,21 @@ interface nsMsgDBCommitType
[ref] native nsMsgKeyArrayRef(nsMsgKeyArray);
[ptr] native nsMsgKeyArrayPtr(nsMsgKeyArray);
[scriptable, uuid(03223c50-1e88-45e8-ba1a-7ce792dc3fc3)]
interface nsIMsgDBService : nsISupports
{
// want to remove this method from nsIMsgDatabase...
// if a db is opened on the folder, the listener will automatically be added
nsIMsgDatabase openFolderDB(in nsIMsgFolder aFolder, in boolean aCreate, in boolean aUpgrading);
nsIMsgDatabase openMailDBFromFileSpec(in nsIFileSpec aFolderName, in boolean aCreate, in boolean aUpgrading);
void registerPendingListener(in nsIMsgFolder aFolder, in nsIDBChangeListener aListener);
void unregisterPendingListener(in nsIDBChangeListener aListener);
};
[scriptable, uuid(f667dcb8-5aae-4e71-8559-2a48d7e508cd)]
interface nsIMsgDatabase : nsIDBChangeAnnouncer {
nsIMsgDatabase Open(in nsIFileSpec aFolderName, in boolean aCreate, in boolean aUpgrading);
nsIMsgDatabase OpenFolderDB(in nsIMsgFolder aFolder, in boolean aCreate, in boolean aUpgrading);
void Open(in nsIFileSpec aFolderName, in boolean aCreate, in boolean aUpgrading);
void forceFolderDBClosed(in nsIMsgFolder aFolder);
void Close(in boolean aForceCommit);

View File

@ -48,10 +48,9 @@ public:
nsImapMailDatabase();
virtual ~nsImapMailDatabase();
NS_IMETHOD Open(nsIFileSpec *folderName, PRBool create, PRBool upgrading, nsIMsgDatabase** pMessageDB);
NS_IMETHOD StartBatch();
NS_IMETHOD EndBatch();
NS_IMETHOD GetSummaryValid(PRBool *aResult);
NS_IMETHOD SetSummaryValid(PRBool valid = PR_TRUE);
NS_IMETHOD DeleteMessages(nsMsgKeyArray* nsMsgKeys, nsIDBChangeListener *instigator);
virtual nsresult AdjustExpungedBytesOnDelete(nsIMsgDBHdr *msgHdr);

View File

@ -52,7 +52,7 @@ class nsMailDatabase : public nsMsgDatabase
public:
nsMailDatabase();
virtual ~nsMailDatabase();
NS_IMETHOD Open(nsIFileSpec *aFolderName, PRBool create, PRBool upgrading, nsIMsgDatabase** pMessageDB);
NS_IMETHOD Open(nsIFileSpec *aFolderName, PRBool create, PRBool upgrading);
NS_IMETHOD ForceClosed();
NS_IMETHOD DeleteMessages(nsMsgKeyArray* nsMsgKeys, nsIDBChangeListener *instigator);

View File

@ -52,6 +52,7 @@
#include "nsICollation.h"
#include "nsIMimeConverter.h"
#include "nsCOMPtr.h"
#include "nsCOMArray.h"
#include "nsHashtable.h"
#include "pldhash.h"
class ListContext;
@ -64,12 +65,28 @@ class nsIMsgHeaderParser;
const PRInt32 kMsgDBVersion = 1;
class nsMsgDatabase : public nsIMsgDatabase
class nsMsgDBService : public nsIMsgDBService
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMSGDBSERVICE
nsMsgDBService();
~nsMsgDBService();
protected:
nsCOMArray <nsIMsgFolder> m_foldersPendingListeners;
nsCOMArray <nsIDBChangeListener> m_pendingListeners;
};
class nsMsgDatabase : public nsIMsgDatabase
{
public:
friend class nsMsgDBService;
NS_DECL_ISUPPORTS
NS_DECL_NSIDBCHANGEANNOUNCER
NS_DECL_NSIMSGDATABASE
virtual nsresult IsHeaderRead(nsIMsgDBHdr *hdr, PRBool *pRead);
virtual nsresult MarkHdrReadInDB(nsIMsgDBHdr *msgHdr, PRBool bRead,
nsIDBChangeListener *instigator);
@ -99,6 +116,7 @@ public:
mdb_token &scopeToken, mdb_token &kindToken);
static nsMsgDatabase* FindInCache(nsFileSpec &dbName);
static nsIMsgDatabase* FindInCache(nsIMsgFolder *folder);
//helper function to fill in nsStrings from hdr row cell contents.
nsresult RowCellColumnTonsString(nsIMdbRow *row, mdb_token columnToken, nsAString &resultStr);

View File

@ -55,24 +55,23 @@ public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSINEWSDATABASE
NS_IMETHOD Open(nsIFileSpec *newsgroupName, PRBool create, PRBool upgrading, nsIMsgDatabase** pMessageDB);
NS_IMETHOD Close(PRBool forceCommit);
NS_IMETHOD ForceClosed();
NS_IMETHOD Commit(nsMsgDBCommit commitType);
virtual PRUint32 GetCurVersion();
NS_IMETHOD Close(PRBool forceCommit);
NS_IMETHOD ForceClosed();
NS_IMETHOD Commit(nsMsgDBCommit commitType);
virtual PRUint32 GetCurVersion();
// methods to get and set docsets for ids.
NS_IMETHOD IsRead(nsMsgKey key, PRBool *pRead);
NS_IMETHOD IsRead(nsMsgKey key, PRBool *pRead);
virtual nsresult IsHeaderRead(nsIMsgDBHdr *msgHdr, PRBool *pRead);
NS_IMETHOD GetHighWaterArticleNum(nsMsgKey *key);
NS_IMETHOD GetLowWaterArticleNum(nsMsgKey *key);
NS_IMETHOD GetHighWaterArticleNum(nsMsgKey *key);
NS_IMETHOD GetLowWaterArticleNum(nsMsgKey *key);
NS_IMETHOD MarkAllRead(nsMsgKeyArray *thoseMarked);
virtual nsresult ExpireUpTo(nsMsgKey expireKey);
virtual nsresult ExpireRange(nsMsgKey startRange, nsMsgKey endRange);
virtual nsresult ExpireUpTo(nsMsgKey expireKey);
virtual nsresult ExpireRange(nsMsgKey startRange, nsMsgKey endRange);
virtual PRBool SetHdrReadFlag(nsIMsgDBHdr *msgHdr, PRBool bRead);
virtual PRBool SetHdrReadFlag(nsIMsgDBHdr *msgHdr, PRBool bRead);
virtual nsresult AdjustExpungedBytesOnDelete(nsIMsgDBHdr *msgHdr);
nsresult SyncWithReadSet();
@ -83,10 +82,6 @@ public:
protected:
virtual PRBool ThreadBySubjectWithoutRe() ;
// MSG_FilterList* m_filterList;
// at a specified entry.
// this is owned by the nsNewsFolder, which lives longer than the db.
nsMsgKeySet *m_readSet;
};

View File

@ -60,122 +60,11 @@ nsImapMailDatabase::~nsImapMailDatabase()
{
}
NS_IMETHODIMP nsImapMailDatabase::Open(nsIFileSpec *aFolderName, PRBool create, PRBool upgrading, nsIMsgDatabase** pMessageDB)
NS_IMETHODIMP nsImapMailDatabase::GetSummaryValid(PRBool *aResult)
{
nsImapMailDatabase *mailDB;
PRBool summaryFileExists;
struct stat st;
PRBool newFile = PR_FALSE;
#ifdef DEBUG_bienvenu
NS_ASSERTION(m_folder, "folder should be set");
#endif
if (!aFolderName)
return NS_ERROR_NULL_POINTER;
nsFileSpec folderName;
aFolderName->GetFileSpec(&folderName);
nsLocalFolderSummarySpec summarySpec(folderName);
nsIDBFolderInfo *folderInfo = NULL;
*pMessageDB = NULL;
nsFileSpec dbPath(summarySpec);
mailDB = (nsImapMailDatabase *) FindInCache(dbPath);
if (mailDB)
{
*pMessageDB = mailDB;
return(NS_OK);
}
#if defined(DEBUG_bienvenu) || defined(DEBUG_jefft)
printf("really opening db in nsImapMailDatabase::Open(%s, %s, %p, %s) -> %s\n",
(const char*)folderName, create ? "TRUE":"FALSE",
pMessageDB, upgrading ? "TRUE":"FALSE", (const char*)folderName);
#endif
// if the old summary doesn't exist, we're creating a new one.
if (!summarySpec.Exists() && create)
newFile = PR_TRUE;
mailDB = new nsImapMailDatabase;
if (!mailDB)
return NS_ERROR_OUT_OF_MEMORY;
mailDB->m_folderSpec = new nsFileSpec(folderName);
mailDB->m_folder = m_folder;
mailDB->AddRef();
// stat file before we open the db, because if we've latered
// any messages, handling latered will change time stamp on
// folder file.
summaryFileExists = summarySpec.Exists();
char *nativeFolderName = nsCRT::strdup((const char *) folderName);
#if defined(XP_WIN) || defined(XP_OS2) || defined(XP_MAC)
UnixToNative(nativeFolderName);
#endif
stat (nativeFolderName, &st);
PR_FREEIF(nativeFolderName);
nsresult err = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
err = mailDB->OpenMDB((const char *) summarySpec, create);
if (err == NS_OK)
{
mailDB->GetDBFolderInfo(&folderInfo);
if (folderInfo == NULL)
{
err = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
}
else
{
// compare current version of db versus filed out version info.
PRUint32 version;
folderInfo->GetVersion(&version);
if (mailDB->GetCurVersion() != version)
err = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
NS_RELEASE(folderInfo);
}
if (err != NS_OK)
{
// this will make the db folder info release its ref to the mail db...
NS_IF_RELEASE(mailDB->m_dbFolderInfo);
mailDB->ForceClosed();
if (err == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
summarySpec.Delete(PR_FALSE);
mailDB = NULL;
}
}
if (err != NS_OK || newFile)
{
// if we couldn't open file, or we have a blank one, and we're supposed
// to upgrade, updgrade it.
if (newFile && !upgrading) // caller is upgrading, and we have empty summary file,
{ // leave db around and open so caller can upgrade it.
err = NS_MSG_ERROR_FOLDER_SUMMARY_MISSING;
}
else if (err != NS_OK)
{
*pMessageDB = NULL;
if (mailDB)
mailDB->Close(PR_FALSE);
delete mailDB;
summarySpec.Delete(PR_FALSE); // blow away the db if it's corrupt.
mailDB = NULL;
}
}
if (err == NS_OK || err == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
{
*pMessageDB = mailDB;
if (mailDB)
GetDBCache()->AppendElement(mailDB);
}
return err;
NS_ENSURE_ARG_POINTER(aResult);
*aResult = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP nsImapMailDatabase::SetSummaryValid(PRBool /* valid */)

View File

@ -89,112 +89,16 @@ void nsMailDatabase::GetGlobalPrefs()
gGotGlobalPrefs = PR_TRUE;
}
}
// caller passes in upgrading==PR_TRUE if they want back a db even if the db is out of date.
// If so, they'll extract out the interesting info from the db, close it, delete it, and
// then try to open the db again, prior to reparsing.
NS_IMETHODIMP nsMailDatabase::Open(nsIFileSpec *aFolderName, PRBool create, PRBool upgrading, nsIMsgDatabase** pMessageDB)
NS_IMETHODIMP nsMailDatabase::Open(nsIFileSpec *aFolderName, PRBool aCreate, PRBool aUpgrading)
{
nsMailDatabase *mailDB;
PRBool summaryFileExists;
PRBool newFile = PR_FALSE;
PRBool deleteInvalidDB = PR_FALSE;
nsFileSpec folderName;
if (!aFolderName)
return NS_ERROR_NULL_POINTER;
nsFileSpec folderName;
aFolderName->GetFileSpec(&folderName);
nsLocalFolderSummarySpec summarySpec(folderName);
nsIDBFolderInfo *folderInfo = nsnull;
*pMessageDB = nsnull;
nsFileSpec dbPath(summarySpec);
mailDB = (nsMailDatabase *) FindInCache(dbPath);
if (mailDB)
{
*pMessageDB = mailDB;
//FindInCache does the AddRef'ing
return(NS_OK);
}
// if the old summary doesn't exist, we're creating a new one.
if ((!summarySpec.Exists() || !summarySpec.GetFileSize()) && create)
newFile = PR_TRUE;
mailDB = new nsMailDatabase();
if (!mailDB)
return NS_ERROR_OUT_OF_MEMORY;
mailDB->m_folderSpec = new nsFileSpec(folderName);
mailDB->m_folder = m_folder;
mailDB->AddRef();
// treat empty summary file as not existing...so we can create and parse it.
summaryFileExists = summarySpec.Exists() && summarySpec.GetFileSize() > 0;
nsresult err = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
err = mailDB->OpenMDB((const char *) summarySpec, create);
if (NS_SUCCEEDED(err))
{
mailDB->GetDBFolderInfo(&folderInfo);
if (folderInfo == NULL)
{
err = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
}
else
{
// if opening existing file, make sure summary file is up to date.
if (!newFile && summaryFileExists)
{
PRBool valid;
mailDB->GetSummaryValid(&valid);
if (!valid)
err = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
}
NS_RELEASE(folderInfo);
}
if (NS_FAILED(err) && !upgrading)
deleteInvalidDB = PR_TRUE;
}
else
{
err = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
deleteInvalidDB = PR_TRUE;
}
if (deleteInvalidDB)
{
// this will make the db folder info release its ref to the mail db...
NS_IF_RELEASE(mailDB->m_dbFolderInfo);
mailDB->ForceClosed();
NS_RELEASE(mailDB); // this sets mailDB to nsnull and makes ref count go to 0
if (err == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
summarySpec.Delete(PR_FALSE);
}
if (err != NS_OK || newFile)
{
// if we couldn't open file, or we have a blank one, and we're supposed
// to upgrade, updgrade it.
if (newFile && !upgrading) // caller is upgrading, and we have empty summary file,
{ // leave db around and open so caller can upgrade it.
err = NS_MSG_ERROR_FOLDER_SUMMARY_MISSING;
}
else if (err != NS_OK && deleteInvalidDB)
{
NS_IF_RELEASE(mailDB);
}
}
if (err == NS_OK || !deleteInvalidDB)
{
*pMessageDB = mailDB;
if (mailDB)
GetDBCache()->AppendElement(mailDB);
}
return (summaryFileExists) ? err : NS_MSG_ERROR_FOLDER_SUMMARY_MISSING;
m_folderSpec = new nsFileSpec(folderName);
nsresult rv = nsMsgDatabase::Open(aFolderName, aCreate, aUpgrading);
return rv;
}
NS_IMETHODIMP nsMailDatabase::ForceClosed()

View File

@ -42,16 +42,36 @@
#include "nsIFactory.h"
#include "nsIComponentManager.h"
// 03223c50-1e88-45e8-ba1a-7ce792dc3fc3
#define NS_MSGDB_SERVICE_CID \
{ 0x03223c50, 0x1e88, 0x45e8, \
{ 0xba, 0x1a, 0x7c, 0xe7, 0x92, 0xdc, 0x3f, 0xc3 } }
#define NS_MSGDB_SERVICE_CONTRACTID \
"@mozilla.org/msgDatabase/msgDBService;1"
#define NS_MSGDB_CONTRACTID \
"@mozilla.org/nsMsgDatabase/msgDB-"
#define NS_MAILBOXDB_CONTRACTID \
NS_MSGDB_CONTRACTID"mailbox"
// a86c86ae-e97f-11d2-a506-0060b0fc04b7
#define NS_MAILDB_CID \
{ 0xa86c86ae, 0xe97f, 0x11d2, \
{ 0xa5, 0x06, 0x00, 0x60, 0xb0, 0xfc, 0x04, 0xb7 } }
#define NS_NEWSDB_CONTRACTID \
NS_MSGDB_CONTRACTID"news"
// 36414aa0-e980-11d2-a506-0060b0fc04b7
#define NS_NEWSDB_CID \
{ 0x36414aa0, 0xe980, 0x11d2, \
{ 0xa5, 0x06, 0x00, 0x60, 0xb0, 0xfc, 0x04, 0xb7 } }
#define NS_IMAPDB_CONTRACTID \
NS_MSGDB_CONTRACTID"imap"
// 9e4b07ee-e980-11d2-a506-0060b0fc04b7
#define NS_IMAPDB_CID \
{ 0x9e4b07ee, 0xe980, 0x11d2, \

View File

@ -21,6 +21,7 @@
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
* David Bienvenu <bienvenu@mozilla.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -64,12 +65,12 @@
#include "nsTime.h"
#include "nsIFileSpec.h"
#include "nsLocalFolderSummarySpec.h"
#include "nsMsgDBCID.h"
#include "nsILocale.h"
#include "nsLocaleCID.h"
#include "nsMsgMimeCID.h"
#include "nsILocaleService.h"
#include "nsMsgFolderFlags.h"
#include "nsIMsgAccountManager.h"
#include "nsIMsgFolderCache.h"
#include "nsIMsgFolderCacheElement.h"
@ -103,6 +104,122 @@ static const nsMsgKey kAllThreadsTableKey = 0xfffffffd;
static const nsMsgKey kFirstPseudoKey = 0xfffffff0;
static const nsMsgKey kIdStartOfFake = 0xffffff80;
NS_IMPL_ISUPPORTS1(nsMsgDBService, nsIMsgDBService)
nsMsgDBService::nsMsgDBService()
{
}
nsMsgDBService::~nsMsgDBService()
{
}
NS_IMETHODIMP nsMsgDBService::OpenFolderDB(nsIMsgFolder *aFolder, PRBool aCreate, PRBool aUpgrading, nsIMsgDatabase **_retval)
{
NS_ENSURE_ARG(aFolder);
*_retval = nsMsgDatabase::FindInCache(aFolder);
if (*_retval)
return NS_OK;
nsCOMPtr <nsIMsgIncomingServer> incomingServer;
nsresult rv = aFolder->GetServer(getter_AddRefs(incomingServer));
NS_ENSURE_SUCCESS(rv, rv);
nsXPIDLCString localStoreType;
incomingServer->GetLocalStoreType(getter_Copies(localStoreType));
nsCAutoString dbContractID(NS_MSGDB_CONTRACTID);
dbContractID.Append(localStoreType.get());
nsCOMPtr <nsIMsgDatabase> msgDB = do_CreateInstance(dbContractID.get(), &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr <nsIFileSpec> folderPath;
rv = aFolder->GetPath(getter_AddRefs(folderPath));
NS_ENSURE_SUCCESS(rv, rv);
rv = msgDB->Open(folderPath, aCreate, aUpgrading);
if (NS_FAILED(rv) && (rv != NS_MSG_ERROR_FOLDER_SUMMARY_MISSING
&& rv != NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE || !aCreate))
return rv;
NS_IF_ADDREF(*_retval = msgDB);
nsMsgDatabase *msgDatabase = NS_STATIC_CAST(nsMsgDatabase *, *_retval);
msgDatabase->m_folder = aFolder;
PRUint32 folderFlags;
aFolder->GetFlags(&folderFlags);
if (NS_SUCCEEDED(rv) && ! (folderFlags & MSG_FOLDER_FLAG_VIRTUAL))
{
mdb_count numHdrsInTable = 0;
if (msgDatabase->m_mdbAllMsgHeadersTable)
{
PRInt32 numMessages;
msgDatabase->m_mdbAllMsgHeadersTable->GetCount(msgDatabase->GetEnv(), &numHdrsInTable);
msgDatabase->m_dbFolderInfo->GetNumMessages(&numMessages);
if (numMessages != numHdrsInTable)
msgDatabase->SyncCounts();
}
}
NS_ENSURE_SUCCESS(rv, rv);
for (PRInt32 listenerIndex = 0; listenerIndex < m_foldersPendingListeners.Count(); listenerIndex++)
{
// check if we have a pending listener on this db, and if so, add it.
if (m_foldersPendingListeners[listenerIndex] == aFolder)
(*_retval)->AddListener(m_pendingListeners.ObjectAt(listenerIndex));
}
return rv;
}
NS_IMETHODIMP nsMsgDBService::OpenMailDBFromFileSpec(nsIFileSpec *aFolderName, PRBool aCreate, PRBool aUpgrading, nsIMsgDatabase** pMessageDB)
{
nsFileSpec folderName;
if (!aFolderName)
return NS_ERROR_NULL_POINTER;
aFolderName->GetFileSpec(&folderName);
nsLocalFolderSummarySpec summarySpec(folderName);
nsFileSpec dbPath(summarySpec);
*pMessageDB = (nsMsgDatabase *) nsMsgDatabase::FindInCache(dbPath);
if (*pMessageDB)
return NS_OK;
nsresult rv;
nsCOMPtr <nsIMsgDatabase> msgDB = do_CreateInstance(NS_MAILBOXDB_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = msgDB->Open(aFolderName, aCreate, aUpgrading);
NS_IF_ADDREF(*pMessageDB = msgDB);
return rv;
}
/* void registerPendingListener (in nsIMsgFolder aFolder, in nsIDBChangeListener aListener); */
NS_IMETHODIMP nsMsgDBService::RegisterPendingListener(nsIMsgFolder *aFolder, nsIDBChangeListener *aListener)
{
// need to make sure we don't hold onto these forever. Maybe a shutdown listener?
// if there is a db open on this folder already, we should register the listener.
m_foldersPendingListeners.AppendObject(aFolder);
m_pendingListeners.AppendObject(aListener);
nsCOMPtr <nsIMsgDatabase> openDB;
openDB = getter_AddRefs((nsIMsgDatabase *) nsMsgDatabase::FindInCache(aFolder));
if (openDB)
openDB->AddListener(aListener);
return NS_OK;
}
/* void unregisterPendingListener (in nsIDBChangeListener aListener); */
NS_IMETHODIMP nsMsgDBService::UnregisterPendingListener(nsIDBChangeListener *aListener)
{
PRInt32 listenerIndex = m_pendingListeners.IndexOfObject(aListener);
if (listenerIndex != kNotFound)
{
nsCOMPtr <nsIMsgFolder> folder = m_foldersPendingListeners[listenerIndex];
nsCOMPtr <nsIMsgDatabase> msgDB = getter_AddRefs(nsMsgDatabase::FindInCache(folder));
if (msgDB)
msgDB->RemoveListener(aListener);
m_foldersPendingListeners.RemoveObjectAt(listenerIndex);
m_pendingListeners.RemoveObjectAt(listenerIndex);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
// we never need to call this because we check the use cache first,
// and any hdr in this cache will be in the use cache.
@ -673,6 +790,22 @@ nsMsgDatabase* nsMsgDatabase::FindInCache(nsFileSpec &dbName)
return nsnull;
}
//----------------------------------------------------------------------
// FindInCache(nsIMsgFolder) - this addrefs the db it finds.
//----------------------------------------------------------------------
nsIMsgDatabase* nsMsgDatabase::FindInCache(nsIMsgFolder *folder)
{
nsCOMPtr <nsIFileSpec> folderPath;
nsFileSpec folderName;
nsresult rv = folder->GetPath(getter_AddRefs(folderPath));
NS_ENSURE_SUCCESS(rv, nsnull);
folderPath->GetFileSpec(&folderName);
nsLocalFolderSummarySpec summarySpec(folderName);
nsFileSpec dbPath(summarySpec);
return (nsIMsgDatabase *) FindInCache(dbPath);
}
//----------------------------------------------------------------------
// FindInCache
//----------------------------------------------------------------------
@ -797,6 +930,7 @@ nsMsgDatabase::~nsMsgDatabase()
m_mdbEnv->Release(); //??? is this right?
m_mdbEnv = nsnull;
}
NotifyAnnouncerGoingAway();
if (m_ChangeListeners)
{
//better not be any listeners, because we're going away.
@ -918,35 +1052,102 @@ void nsMsgDatabase::UnixToNative(char*& ioPath)
#endif /* XP_MAC */
NS_IMETHODIMP nsMsgDatabase::OpenFolderDB(nsIMsgFolder *folder, PRBool create, PRBool upgrading, nsIMsgDatabase** pMessageDB)
// caller passes in upgrading==PR_TRUE if they want back a db even if the db is out of date.
// If so, they'll extract out the interesting info from the db, close it, delete it, and
// then try to open the db again, prior to reparsing.
NS_IMETHODIMP nsMsgDatabase::Open(nsIFileSpec *aFolderName, PRBool aCreate, PRBool aUpgrading)
{
NS_ENSURE_ARG(folder);
m_folder = folder;
nsCOMPtr <nsIFileSpec> folderPath;
nsresult rv = folder->GetPath(getter_AddRefs(folderPath));
NS_ENSURE_SUCCESS(rv, rv);
rv = Open(folderPath, create, upgrading, pMessageDB);
if (NS_SUCCEEDED(rv))
PRBool summaryFileExists;
PRBool newFile = PR_FALSE;
PRBool deleteInvalidDB = PR_FALSE;
#ifdef DEBUG_bienvenu
NS_ASSERTION(m_folder, "folder should be set");
#endif
if (!aFolderName)
return NS_ERROR_NULL_POINTER;
nsFileSpec folderName;
aFolderName->GetFileSpec(&folderName);
nsLocalFolderSummarySpec summarySpec(folderName);
nsIDBFolderInfo *folderInfo = nsnull;
#if defined(DEBUG_bienvenu) || defined(DEBUG_jefft)
printf("really opening db in nsImapMailDatabase::Open(%s, %s, %p, %s) -> %s\n",
(const char*)folderName, aCreate ? "TRUE":"FALSE",
this, aUpgrading ? "TRUE":"FALSE", (const char*)folderName);
#endif
// if the old summary doesn't exist, we're creating a new one.
if ((!summarySpec.Exists() || !summarySpec.GetFileSize()) && aCreate)
newFile = PR_TRUE;
// stat file before we open the db, because if we've latered
// any messages, handling latered will change time stamp on
// folder file.
summaryFileExists = summarySpec.Exists() && summarySpec.GetFileSize() > 0;
nsresult err = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
err = OpenMDB((const char *) summarySpec, aCreate);
if (NS_SUCCEEDED(err))
{
mdb_count numHdrsInTable = 0;
if (m_mdbAllMsgHeadersTable)
GetDBFolderInfo(&folderInfo);
if (folderInfo == NULL)
{
PRInt32 numMessages;
m_mdbAllMsgHeadersTable->GetCount(GetEnv(), &numHdrsInTable);
m_dbFolderInfo->GetNumMessages(&numMessages);
if (numMessages != numHdrsInTable)
SyncCounts();
err = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
}
else
{
if (!newFile && summaryFileExists)
{
PRBool valid;
GetSummaryValid(&valid);
if (!valid)
err = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
}
// compare current version of db versus filed out version info.
PRUint32 version;
folderInfo->GetVersion(&version);
if (GetCurVersion() != version)
err = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
NS_RELEASE(folderInfo);
}
if (NS_FAILED(err) && !aUpgrading)
deleteInvalidDB = PR_TRUE;
}
else
{
err = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
deleteInvalidDB = PR_TRUE;
}
if (deleteInvalidDB)
{
// this will make the db folder info release its ref to the mail db...
NS_IF_RELEASE(m_dbFolderInfo);
ForceClosed();
if (err == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
summarySpec.Delete(PR_FALSE);
}
if (err != NS_OK || newFile)
{
// if we couldn't open file, or we have a blank one, and we're supposed
// to upgrade, updgrade it.
if (newFile && !aUpgrading) // caller is upgrading, and we have empty summary file,
{ // leave db around and open so caller can upgrade it.
err = NS_MSG_ERROR_FOLDER_SUMMARY_MISSING;
}
else if (err != NS_OK)
{
Close(PR_FALSE);
summarySpec.Delete(PR_FALSE); // blow away the db if it's corrupt.
}
}
return rv;
}
NS_IMETHODIMP nsMsgDatabase::Open(nsIFileSpec *folderName, PRBool create, PRBool upgrading, nsIMsgDatabase** pMessageDB)
{
NS_ASSERTION(PR_FALSE, "must override");
return NS_ERROR_NOT_IMPLEMENTED;
if (err == NS_OK || err == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
GetDBCache()->AppendElement(this);
return (summaryFileExists) ? err : NS_MSG_ERROR_FOLDER_SUMMARY_MISSING;
}
// Open the MDB database synchronously. If successful, this routine

View File

@ -39,7 +39,6 @@
#include "msgCore.h"
#include "nsNewsDatabase.h"
#include "nsNewsSummarySpec.h"
#include "nsMsgKeySet.h"
#include "nsCOMPtr.h"
#include "prlog.h"
@ -80,108 +79,6 @@ NS_IMETHODIMP nsNewsDatabase::QueryInterface(REFNSIID aIID, void** aInstancePtr)
return nsMsgDatabase::QueryInterface(aIID, aInstancePtr);
}
NS_IMETHODIMP nsNewsDatabase::Open(nsIFileSpec *aNewsgroupName, PRBool create, PRBool upgrading, nsIMsgDatabase** pMessageDB)
{
nsNewsDatabase *newsDB;
if (!aNewsgroupName)
return NS_ERROR_NULL_POINTER;
nsFileSpec newsgroupName;
aNewsgroupName->GetFileSpec(&newsgroupName);
nsNewsSummarySpec summarySpec(newsgroupName);
nsresult err = NS_OK;
PRBool newFile = PR_FALSE;
#ifdef DEBUG_NEWS_DATABASE
printf("nsNewsDatabase::Open(%s, %s, %p, %s) -> %s\n",
(const char*)newsgroupName, create ? "TRUE":"FALSE",
pMessageDB, upgrading ? "TRUE":"FALSE", (const char *)summarySpec);
#endif
nsFileSpec dbPath(summarySpec);
*pMessageDB = nsnull;
newsDB = (nsNewsDatabase *) FindInCache(dbPath);
if (newsDB)
{
*pMessageDB = newsDB;
//FindInCache does the AddRef'ing
//newsDB->AddRef();
return(NS_OK);
}
newsDB = new nsNewsDatabase();
newsDB->m_folder = m_folder;
if (!newsDB) {
#ifdef DEBUG_NEWS_DATABASE
printf("NS_ERROR_OUT_OF_MEMORY\n");
#endif
return NS_ERROR_OUT_OF_MEMORY;
}
newsDB->AddRef();
nsIDBFolderInfo *folderInfo = nsnull;
err = newsDB->OpenMDB((const char *) summarySpec, create);
if (err == NS_OK)
{
newsDB->GetDBFolderInfo(&folderInfo);
if (folderInfo == nsnull)
{
err = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
}
else
{
// compare current version of db versus filed out version info.
PRUint32 version;
folderInfo->GetVersion(&version);
if (newsDB->GetCurVersion() != version)
err = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
NS_RELEASE(folderInfo);
}
if (err != NS_OK)
{
// this will make the db folder info release its ref to the mail db...
NS_IF_RELEASE(newsDB->m_dbFolderInfo);
newsDB->ForceClosed();
if (err == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
summarySpec.Delete(PR_FALSE);
newsDB = nsnull;
}
}
if (err != NS_OK || newFile)
{
// if we couldn't open file, or we have a blank one, and we're supposed
// to upgrade, updgrade it.
if (newFile && !upgrading) // caller is upgrading, and we have empty summary file,
{ // leave db around and open so caller can upgrade it.
err = NS_MSG_ERROR_FOLDER_SUMMARY_MISSING;
}
else if (err != NS_OK)
{
*pMessageDB = nsnull;
if (newsDB)
newsDB->ForceClosed();
delete newsDB;
summarySpec.Delete(PR_FALSE); // blow away the db if it's corrupt.
newsDB = nsnull;
}
}
if (err == NS_OK || err == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
{
*pMessageDB = newsDB;
if (newsDB)
GetDBCache()->AppendElement(newsDB);
}
return err;
}
nsresult nsNewsDatabase::Close(PRBool forceCommit)
{
return nsMsgDatabase::Close(forceCommit);

View File

@ -612,14 +612,12 @@ nsresult nsImapMailFolder::GetDatabase(nsIMsgWindow *aMsgWindow)
nsresult rv = GetPath(getter_AddRefs(pathSpec));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIMsgDatabase> mailDBFactory;
rv = nsComponentManager::CreateInstance(kCImapDB, nsnull, NS_GET_IID(nsIMsgDatabase), (void **) getter_AddRefs(mailDBFactory));
if (NS_SUCCEEDED(rv) && mailDBFactory)
folderOpen = mailDBFactory->OpenFolderDB(this, PR_TRUE, PR_FALSE, getter_AddRefs(mDatabase));
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
if (msgDBService)
folderOpen = msgDBService->OpenFolderDB(this, PR_TRUE, PR_FALSE, getter_AddRefs(mDatabase));
if(folderOpen == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING || folderOpen == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
folderOpen = mailDBFactory->OpenFolderDB(this, PR_TRUE, PR_TRUE, getter_AddRefs(mDatabase));
folderOpen = msgDBService->OpenFolderDB(this, PR_TRUE, PR_TRUE, getter_AddRefs(mDatabase));
if(mDatabase)
{
@ -878,8 +876,8 @@ NS_IMETHODIMP nsImapMailFolder::CreateClientSubfolderInfo(const char *folderName
nsCOMPtr<nsIMsgDatabase> mailDBFactory;
nsCOMPtr<nsIMsgFolder> child;
rv = nsComponentManager::CreateInstance(kCImapDB, nsnull, NS_GET_IID(nsIMsgDatabase), (void **) getter_AddRefs(mailDBFactory));
if (NS_SUCCEEDED(rv) && mailDBFactory)
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
if (msgDBService)
{
nsCOMPtr<nsIMsgDatabase> unusedDB;
nsCOMPtr <nsIFileSpec> dbFileSpec;
@ -891,7 +889,7 @@ NS_IMETHODIMP nsImapMailFolder::CreateClientSubfolderInfo(const char *folderName
//Now let's create the actual new folder
rv = AddSubfolderWithPath(folderNameStr, dbFileSpec, getter_AddRefs(child));
NS_ENSURE_SUCCESS(rv, rv);
rv = mailDBFactory->OpenFolderDB(child, PR_TRUE, PR_TRUE, (nsIMsgDatabase **) getter_AddRefs(unusedDB));
rv = msgDBService->OpenFolderDB(child, PR_TRUE, PR_TRUE, (nsIMsgDatabase **) getter_AddRefs(unusedDB));
if (NS_SUCCEEDED(rv) && unusedDB)
{
@ -2531,9 +2529,6 @@ NS_IMETHODIMP nsImapMailFolder::UpdateImapMailboxInfo(
if ((imapUIDValidity != folderValidity) /* && // if UIDVALIDITY Changed
!NET_IsOffline() */)
{
nsCOMPtr<nsIMsgDatabase> mailDBFactory;
nsCOMPtr<nsIFileSpec> pathSpec;
rv = GetPath(getter_AddRefs(pathSpec));
if (NS_FAILED(rv)) return rv;
@ -2542,10 +2537,8 @@ NS_IMETHODIMP nsImapMailFolder::UpdateImapMailboxInfo(
rv = pathSpec->GetFileSpec(&dbName);
if (NS_FAILED(rv)) return rv;
rv = nsComponentManager::CreateInstance(kCImapDB, nsnull,
NS_GET_IID(nsIMsgDatabase),
(void **) getter_AddRefs(mailDBFactory));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr <nsIDBFolderInfo> transferInfo;
if (dbFolderInfo)
@ -2563,7 +2556,7 @@ NS_IMETHODIMP nsImapMailFolder::UpdateImapMailboxInfo(
// Create a new summary file, update the folder message counts, and
// Close the summary file db.
rv = mailDBFactory->OpenFolderDB(this, PR_TRUE, PR_TRUE, getter_AddRefs(mDatabase));
rv = msgDBService->OpenFolderDB(this, PR_TRUE, PR_TRUE, getter_AddRefs(mDatabase));
// ********** Important *************
// David, help me here I don't know this is right or wrong
@ -7227,8 +7220,8 @@ NS_IMETHODIMP nsImapMailFolder::RenameClient(nsIMsgWindow *msgWindow, nsIMsgFold
nsCOMPtr<nsIMsgFolder> child;
nsCOMPtr <nsIMsgImapMailFolder> imapFolder;
rv = nsComponentManager::CreateInstance(kCImapDB, nsnull, NS_GET_IID(nsIMsgDatabase), (void **) getter_AddRefs(mailDBFactory));
if (NS_SUCCEEDED(rv) && mailDBFactory)
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID);
if (msgDBService)
{
nsCOMPtr<nsIMsgDatabase> unusedDB;
nsCOMPtr <nsIFileSpec> dbFileSpec;
@ -7240,8 +7233,8 @@ NS_IMETHODIMP nsImapMailFolder::RenameClient(nsIMsgWindow *msgWindow, nsIMsgFold
rv = CreateFileSpecForDB(proposedDBName.get(), path, getter_AddRefs(dbFileSpec));
NS_ENSURE_SUCCESS(rv,rv);
// it's OK to use Open and not OpenFolderDB here, since we don't use the DB.
rv = mailDBFactory->Open(dbFileSpec, PR_TRUE, PR_TRUE, (nsIMsgDatabase **) getter_AddRefs(unusedDB));
// it's OK to use openMailDBFromFileSpec and not OpenFolderDB here, since we don't use the DB.
rv = msgDBService->OpenMailDBFromFileSpec(dbFileSpec, PR_TRUE, PR_TRUE, (nsIMsgDatabase **) getter_AddRefs(unusedDB));
if (NS_SUCCEEDED(rv) && unusedDB)
{
@ -7286,7 +7279,7 @@ NS_IMETHODIMP nsImapMailFolder::RenameClient(nsIMsgWindow *msgWindow, nsIMsgFold
unusedDB->Commit(nsMsgDBCommitType::kLargeCommit);
unusedDB->Close(PR_TRUE);
child->RenameSubFolders(msgWindow, msgFolder);
child->RenameSubFolders(msgWindow, msgFolder);
nsCOMPtr<nsIMsgFolder> msgParent;
msgFolder->GetParentMsgFolder(getter_AddRefs(msgParent));

View File

@ -348,11 +348,10 @@ NS_IMETHODIMP nsMsgLocalMailFolder::GetDatabaseWOReparse(nsIMsgDatabase **aDatab
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIMsgDatabase> mailDBFactory;
rv = nsComponentManager::CreateInstance(kCMailDB, nsnull, NS_GET_IID(nsIMsgDatabase), (void **) getter_AddRefs(mailDBFactory));
if (NS_SUCCEEDED(rv) && mailDBFactory)
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && msgDBService)
{
rv = mailDBFactory->OpenFolderDB(this, PR_FALSE, PR_FALSE, (nsIMsgDatabase **) getter_AddRefs(mDatabase));
rv = msgDBService->OpenFolderDB(this, PR_FALSE, PR_FALSE, (nsIMsgDatabase **) getter_AddRefs(mDatabase));
if (mDatabase && NS_SUCCEEDED(rv))
mDatabase->AddListener(this);
}
@ -512,12 +511,10 @@ nsresult nsMsgLocalMailFolder::GetDatabase(nsIMsgWindow *aMsgWindow)
if (!exists) return NS_ERROR_NULL_POINTER; //mDatabase will be null at this point.
nsresult folderOpen = NS_OK;
nsCOMPtr<nsIMsgDatabase> mailDBFactory;
rv = nsComponentManager::CreateInstance(kCMailDB, nsnull, NS_GET_IID(nsIMsgDatabase), getter_AddRefs(mailDBFactory));
if (NS_SUCCEEDED(rv) && mailDBFactory)
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
if (msgDBService)
{
folderOpen = mailDBFactory->OpenFolderDB(this, PR_TRUE, PR_TRUE, getter_AddRefs(mDatabase));
folderOpen = msgDBService->OpenFolderDB(this, PR_TRUE, PR_TRUE, getter_AddRefs(mDatabase));
if(NS_FAILED(folderOpen) &&
folderOpen == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
{
@ -549,7 +546,7 @@ nsresult nsMsgLocalMailFolder::GetDatabase(nsIMsgWindow *aMsgWindow)
summarySpec.Delete(PR_FALSE);
// if it's out of date then reopen with upgrade.
if (NS_FAILED(rv = mailDBFactory->OpenFolderDB(this, PR_TRUE, PR_TRUE, getter_AddRefs(mDatabase)))
if (NS_FAILED(rv = msgDBService->OpenFolderDB(this, PR_TRUE, PR_TRUE, getter_AddRefs(mDatabase)))
&& rv != NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
return rv;
else if (transferInfo && mDatabase)
@ -874,13 +871,11 @@ nsMsgLocalMailFolder::CreateSubfolder(const PRUnichar *folderName, nsIMsgWindow
}
// Create an empty database for this mail folder, set its name from the user
nsCOMPtr<nsIMsgDatabase> mailDBFactory;
rv = nsComponentManager::CreateInstance(kCMailDB, nsnull, NS_GET_IID(nsIMsgDatabase), getter_AddRefs(mailDBFactory));
if (NS_SUCCEEDED(rv) && mailDBFactory)
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
if (msgDBService)
{
nsCOMPtr<nsIMsgDatabase> unusedDB;
rv = mailDBFactory->OpenFolderDB(child, PR_TRUE, PR_TRUE, getter_AddRefs(unusedDB));
rv = msgDBService->OpenFolderDB(child, PR_TRUE, PR_TRUE, getter_AddRefs(unusedDB));
if ((NS_SUCCEEDED(rv) || rv == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING
|| rv == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE) && unusedDB)
@ -1117,7 +1112,13 @@ NS_IMETHODIMP nsMsgLocalMailFolder::DeleteSubFolders(
PRBool isChildOfTrash;
rv = IsChildOfTrash(&isChildOfTrash);
if (isChildOfTrash)
// we don't allow multiple folder selection so this is ok.
nsCOMPtr<nsIMsgFolder> folder = do_QueryElementAt(folders, 0);
PRUint32 folderFlags = 0;
if (folder)
folder->GetFlags(&folderFlags);
// when deleting from trash, or virtual folder, just delete it.
if (isChildOfTrash || folderFlags & MSG_FOLDER_FLAG_VIRTUAL)
return nsMsgDBFolder::DeleteSubFolders(folders, msgWindow);
if (!msgWindow)
@ -1127,8 +1128,6 @@ NS_IMETHODIMP nsMsgLocalMailFolder::DeleteSubFolders(
rv = GetTrashFolder(getter_AddRefs(trashFolder));
if (NS_SUCCEEDED(rv))
{
// we don't allow multiple folder selection so this is ok.
nsCOMPtr<nsIMsgFolder> folder = do_QueryElementAt(folders, 0);
if (folder)
trashFolder->CopyFolder(folder, PR_TRUE, msgWindow, nsnull);
}
@ -1355,11 +1354,9 @@ nsMsgLocalMailFolder::GetDBFolderInfoAndDB(nsIDBFolderInfo **folderInfo, nsIMsgD
}
else
{
nsCOMPtr<nsIMsgDatabase> mailDBFactory( do_CreateInstance(kCMailDB, &rv) );
if (NS_SUCCEEDED(rv) && mailDBFactory)
{
openErr = mailDBFactory->OpenFolderDB(this, PR_FALSE, PR_FALSE, getter_AddRefs(mDatabase));
}
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
if (msgDBService)
openErr = msgDBService->OpenFolderDB(this, PR_FALSE, PR_FALSE, getter_AddRefs(mDatabase));
}
*db = mDatabase;

View File

@ -74,64 +74,64 @@ static NS_DEFINE_CID(kCMailDB, NS_MAILDB_CID);
static char *nsMailboxGetURI(const char *nativepath)
{
nsresult rv;
char *uri = nsnull;
nsCOMPtr<nsIMsgAccountManager> accountManager =
do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
if (NS_FAILED(rv)) return nsnull;
nsCOMPtr<nsISupportsArray> serverArray;
accountManager->GetAllServers(getter_AddRefs(serverArray));
// do a char*->fileSpec->char* conversion to normalize the path
nsFilePath filePath(nativepath);
nsresult rv;
char *uri = nsnull;
nsCOMPtr<nsIMsgAccountManager> accountManager =
do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
if (NS_FAILED(rv)) return nsnull;
nsCOMPtr<nsISupportsArray> serverArray;
accountManager->GetAllServers(getter_AddRefs(serverArray));
// do a char*->fileSpec->char* conversion to normalize the path
nsFilePath filePath(nativepath);
PRUint32 cnt;
rv = serverArray->Count(&cnt);
if (NS_FAILED(rv)) return nsnull;
PRInt32 count = cnt;
PRInt32 i;
for (i=0; i<count; i++) {
PRUint32 cnt;
rv = serverArray->Count(&cnt);
if (NS_FAILED(rv)) return nsnull;
PRInt32 count = cnt;
PRInt32 i;
for (i=0; i<count; i++) {
nsCOMPtr<nsIMsgIncomingServer> server = do_QueryElementAt(serverArray, i);
if (!server) continue;
// get the path string, convert it to an nsFilePath
nsCOMPtr<nsIFileSpec> nativeServerPath;
rv = server->GetLocalPath(getter_AddRefs(nativeServerPath));
if (NS_FAILED(rv)) continue;
nsFileSpec spec;
nativeServerPath->GetFileSpec(&spec);
nsFilePath serverPath(spec);
// check if filepath begins with serverPath
PRInt32 len = PL_strlen(serverPath);
if (PL_strncasecmp(serverPath, filePath, len) == 0) {
nsXPIDLCString serverURI;
rv = server->GetServerURI(getter_Copies(serverURI));
if (NS_FAILED(rv)) continue;
// the relpath is just past the serverpath
const char *relpath = nativepath + len;
// skip past leading / if any
while (*relpath == '/') relpath++;
nsCAutoString pathStr(relpath);
PRInt32 sbdIndex;
while((sbdIndex = pathStr.Find(".sbd", PR_TRUE)) != -1)
{
pathStr.Cut(sbdIndex, 4);
}
uri = PR_smprintf("%s/%s", (const char*)serverURI, pathStr.get());
break;
}
nsCOMPtr<nsIMsgIncomingServer> server = do_QueryElementAt(serverArray, i);
if (!server) continue;
// get the path string, convert it to an nsFilePath
nsCOMPtr<nsIFileSpec> nativeServerPath;
rv = server->GetLocalPath(getter_AddRefs(nativeServerPath));
if (NS_FAILED(rv)) continue;
nsFileSpec spec;
nativeServerPath->GetFileSpec(&spec);
nsFilePath serverPath(spec);
// check if filepath begins with serverPath
PRInt32 len = PL_strlen(serverPath);
if (PL_strncasecmp(serverPath, filePath, len) == 0) {
nsXPIDLCString serverURI;
rv = server->GetServerURI(getter_Copies(serverURI));
if (NS_FAILED(rv)) continue;
// the relpath is just past the serverpath
const char *relpath = nativepath + len;
// skip past leading / if any
while (*relpath == '/') relpath++;
nsCAutoString pathStr(relpath);
PRInt32 sbdIndex;
while((sbdIndex = pathStr.Find(".sbd", PR_TRUE)) != -1)
{
pathStr.Cut(sbdIndex, 4);
}
uri = PR_smprintf("%s/%s", (const char*)serverURI, pathStr.get());
break;
}
return uri;
}
return uri;
}
@ -140,12 +140,12 @@ char * extractAttributeValue(const char * searchString, const char * attributeNa
nsMailboxUrl::nsMailboxUrl()
{
m_mailboxAction = nsIMailboxUrl::ActionParseMailbox;
m_filePath = nsnull;
m_messageID = nsnull;
m_messageKey = nsMsgKey_None;
m_messageSize = 0;
m_messageFileSpec = nsnull;
m_mailboxAction = nsIMailboxUrl::ActionParseMailbox;
m_filePath = nsnull;
m_messageID = nsnull;
m_messageKey = nsMsgKey_None;
m_messageSize = 0;
m_messageFileSpec = nsnull;
m_addDummyEnvelope = PR_FALSE;
m_canonicalLineEnding = PR_FALSE;
m_curMsgIndex = 0;
@ -153,8 +153,8 @@ nsMailboxUrl::nsMailboxUrl()
nsMailboxUrl::~nsMailboxUrl()
{
if (m_filePath) delete m_filePath;
PR_FREEIF(m_messageID);
delete m_filePath;
PR_Free(m_messageID);
}
NS_IMPL_ADDREF_INHERITED(nsMailboxUrl, nsMsgMailNewsUrl)
@ -172,68 +172,67 @@ NS_INTERFACE_MAP_END_INHERITING(nsMsgMailNewsUrl)
////////////////////////////////////////////////////////////////////////////////////
nsresult nsMailboxUrl::SetMailboxParser(nsIStreamListener * aMailboxParser)
{
if (aMailboxParser)
m_mailboxParser = aMailboxParser;
return NS_OK;
if (aMailboxParser)
m_mailboxParser = aMailboxParser;
return NS_OK;
}
nsresult nsMailboxUrl::GetMailboxParser(nsIStreamListener ** aConsumer)
{
NS_ENSURE_ARG_POINTER(aConsumer);
*aConsumer = m_mailboxParser;
NS_IF_ADDREF(*aConsumer);
return NS_OK;
NS_IF_ADDREF(*aConsumer = m_mailboxParser);
return NS_OK;
}
nsresult nsMailboxUrl::SetMailboxCopyHandler(nsIStreamListener * aMailboxCopyHandler)
{
if (aMailboxCopyHandler)
m_mailboxCopyHandler = aMailboxCopyHandler;
return NS_OK;
if (aMailboxCopyHandler)
m_mailboxCopyHandler = aMailboxCopyHandler;
return NS_OK;
}
nsresult nsMailboxUrl::GetMailboxCopyHandler(nsIStreamListener ** aMailboxCopyHandler)
{
NS_ENSURE_ARG_POINTER(aMailboxCopyHandler);
if (aMailboxCopyHandler)
{
*aMailboxCopyHandler = m_mailboxCopyHandler;
NS_IF_ADDREF(*aMailboxCopyHandler);
}
return NS_OK;
if (aMailboxCopyHandler)
{
*aMailboxCopyHandler = m_mailboxCopyHandler;
NS_IF_ADDREF(*aMailboxCopyHandler);
}
return NS_OK;
}
nsresult nsMailboxUrl::GetFileSpec(nsFileSpec ** aFilePath)
{
if (aFilePath)
*aFilePath = m_filePath;
return NS_OK;
if (aFilePath)
*aFilePath = m_filePath;
return NS_OK;
}
nsresult nsMailboxUrl::GetMessageKey(nsMsgKey* aMessageKey)
{
*aMessageKey = m_messageKey;
return NS_OK;
*aMessageKey = m_messageKey;
return NS_OK;
}
NS_IMETHODIMP nsMailboxUrl::GetMessageSize(PRUint32 * aMessageSize)
{
if (aMessageSize)
{
*aMessageSize = m_messageSize;
return NS_OK;
}
else
return NS_ERROR_NULL_POINTER;
if (aMessageSize)
{
*aMessageSize = m_messageSize;
return NS_OK;
}
else
return NS_ERROR_NULL_POINTER;
}
nsresult nsMailboxUrl::SetMessageSize(PRUint32 aMessageSize)
{
m_messageSize = aMessageSize;
return NS_OK;
m_messageSize = aMessageSize;
return NS_OK;
}
NS_IMETHODIMP nsMailboxUrl::SetUri(const char * aURI)
@ -246,56 +245,55 @@ NS_IMETHODIMP nsMailboxUrl::GetUri(char ** aURI)
{
// if we have been given a uri to associate with this url, then use it
// otherwise try to reconstruct a URI on the fly....
if (!mURI.IsEmpty())
*aURI = ToNewCString(mURI);
else
{
nsFileSpec * filePath = nsnull;
GetFileSpec(&filePath);
if (filePath)
{
{
nsFileSpec * filePath = nsnull;
GetFileSpec(&filePath);
if (filePath)
{
char * baseuri = nsMailboxGetURI(m_file);
char * baseMessageURI;
nsCreateLocalBaseMessageURI(baseuri, &baseMessageURI);
char * uri = nsnull;
nsCAutoString uriStr;
nsFileSpec folder = *filePath;
nsBuildLocalMessageURI(baseMessageURI, m_messageKey, uriStr);
PL_strfree(baseuri);
nsCRT::free(baseMessageURI);
uri = ToNewCString(uriStr);
*aURI = uri;
}
else
*aURI = nsnull;
}
return NS_OK;
char * baseMessageURI;
nsCreateLocalBaseMessageURI(baseuri, &baseMessageURI);
char * uri = nsnull;
nsCAutoString uriStr;
nsFileSpec folder = *filePath;
nsBuildLocalMessageURI(baseMessageURI, m_messageKey, uriStr);
PL_strfree(baseuri);
nsCRT::free(baseMessageURI);
uri = ToNewCString(uriStr);
*aURI = uri;
}
else
*aURI = nsnull;
}
return NS_OK;
}
nsresult nsMailboxUrl::GetMsgHdrForKey(nsMsgKey msgKey, nsIMsgDBHdr ** aMsgHdr)
{
nsresult rv = NS_OK;
if (aMsgHdr)
{
nsCOMPtr<nsIMsgDatabase> mailDBFactory;
nsCOMPtr<nsIMsgDatabase> mailDB;
rv = nsComponentManager::CreateInstance(kCMailDB, nsnull, NS_GET_IID(nsIMsgDatabase),
(void **) getter_AddRefs(mailDBFactory));
nsCOMPtr <nsIFileSpec> dbFileSpec;
NS_NewFileSpecWithSpec(*m_filePath, getter_AddRefs(dbFileSpec));
if (NS_SUCCEEDED(rv) && mailDBFactory)
rv = mailDBFactory->Open(dbFileSpec, PR_FALSE, PR_FALSE, (nsIMsgDatabase **) getter_AddRefs(mailDB));
if (NS_SUCCEEDED(rv) && mailDB) // did we get a db back?
rv = mailDB->GetMsgHdrForKey(msgKey, aMsgHdr);
}
else
rv = NS_ERROR_NULL_POINTER;
return rv;
nsresult rv = NS_OK;
if (aMsgHdr)
{
nsCOMPtr<nsIMsgDatabase> mailDBFactory;
nsCOMPtr<nsIMsgDatabase> mailDB;
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
nsCOMPtr <nsIFileSpec> dbFileSpec;
NS_NewFileSpecWithSpec(*m_filePath, getter_AddRefs(dbFileSpec));
if (msgDBService)
rv = msgDBService->OpenMailDBFromFileSpec(dbFileSpec, PR_FALSE, PR_FALSE, (nsIMsgDatabase **) getter_AddRefs(mailDB));
if (NS_SUCCEEDED(rv) && mailDB) // did we get a db back?
rv = mailDB->GetMsgHdrForKey(msgKey, aMsgHdr);
}
else
rv = NS_ERROR_NULL_POINTER;
return rv;
}
NS_IMETHODIMP nsMailboxUrl::GetMessageHeader(nsIMsgDBHdr ** aMsgHdr)
@ -323,41 +321,41 @@ nsMailboxUrl::SetOriginalSpec(const char *aSpec)
NS_IMETHODIMP nsMailboxUrl::SetMessageFile(nsIFileSpec * aFileSpec)
{
m_messageFileSpec = aFileSpec;
return NS_OK;
m_messageFileSpec = aFileSpec;
return NS_OK;
}
NS_IMETHODIMP nsMailboxUrl::GetMessageFile(nsIFileSpec ** aFileSpec)
{
if (aFileSpec)
{
*aFileSpec = m_messageFileSpec;
NS_IF_ADDREF(*aFileSpec);
}
return NS_OK;
if (aFileSpec)
{
*aFileSpec = m_messageFileSpec;
NS_IF_ADDREF(*aFileSpec);
}
return NS_OK;
}
NS_IMETHODIMP nsMailboxUrl::IsUrlType(PRUint32 type, PRBool *isType)
{
NS_ENSURE_ARG(isType);
switch(type)
{
case nsIMsgMailNewsUrl::eCopy:
*isType = (m_mailboxAction == nsIMailboxUrl::ActionCopyMessage);
break;
case nsIMsgMailNewsUrl::eMove:
*isType = (m_mailboxAction == nsIMailboxUrl::ActionMoveMessage);
break;
case nsIMsgMailNewsUrl::eDisplay:
*isType = (m_mailboxAction == nsIMailboxUrl::ActionFetchMessage);
break;
default:
*isType = PR_FALSE;
};
return NS_OK;
NS_ENSURE_ARG(isType);
switch(type)
{
case nsIMsgMailNewsUrl::eCopy:
*isType = (m_mailboxAction == nsIMailboxUrl::ActionCopyMessage);
break;
case nsIMsgMailNewsUrl::eMove:
*isType = (m_mailboxAction == nsIMailboxUrl::ActionMoveMessage);
break;
case nsIMsgMailNewsUrl::eDisplay:
*isType = (m_mailboxAction == nsIMailboxUrl::ActionFetchMessage);
break;
default:
*isType = PR_FALSE;
};
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////////
@ -369,46 +367,45 @@ NS_IMETHODIMP nsMailboxUrl::IsUrlType(PRUint32 type, PRBool *isType)
nsresult nsMailboxUrl::ParseSearchPart()
{
nsCAutoString searchPart;
nsresult rv = GetQuery(searchPart);
// add code to this function to decompose everything past the '?'.....
if (NS_SUCCEEDED(rv) && !searchPart.IsEmpty())
{
nsCAutoString searchPart;
nsresult rv = GetQuery(searchPart);
// add code to this function to decompose everything past the '?'.....
if (NS_SUCCEEDED(rv) && !searchPart.IsEmpty())
{
// the action for this mailbox must be a display message...
char * msgPart = extractAttributeValue(searchPart.get(), "part=");
if (msgPart) // if we have a part in the url then we must be fetching just the part.
m_mailboxAction = nsIMailboxUrl::ActionFetchPart;
else
m_mailboxAction = nsIMailboxUrl::ActionFetchMessage;
char * messageKey = extractAttributeValue(searchPart.get(), "number=");
m_messageID = extractAttributeValue(searchPart.get(),"messageid=");
if (messageKey)
m_messageKey = atol(messageKey); // convert to a long...
PR_FREEIF(msgPart);
PR_FREEIF(messageKey);
}
else
m_mailboxAction = nsIMailboxUrl::ActionParseMailbox;
return rv;
m_mailboxAction = nsIMailboxUrl::ActionFetchMessage;
char * messageKey = extractAttributeValue(searchPart.get(), "number=");
m_messageID = extractAttributeValue(searchPart.get(),"messageid=");
if (messageKey)
m_messageKey = atol(messageKey); // convert to a long...
PR_Free(msgPart);
PR_Free(messageKey);
}
else
m_mailboxAction = nsIMailboxUrl::ActionParseMailbox;
return rv;
}
// warning: don't assume when parsing the url that the protocol part is "news"...
nsresult nsMailboxUrl::ParseUrl()
{
if (m_filePath)
delete m_filePath;
GetFilePath(m_file);
ParseSearchPart();
delete m_filePath;
GetFilePath(m_file);
ParseSearchPart();
// ### fix me.
// this hack is to avoid asserting on every local message loaded because the security manager
// is creating an empty "mailbox://" uri for every message.
if (strlen(m_file) < 2)
m_filePath = nsnull;
else
m_filePath = new nsFileSpec(nsFilePath(nsUnescape((char *) (const char *)m_file)));
m_filePath = new nsFileSpec(nsFilePath(nsUnescape((char *) (const char *)m_file)));
return NS_OK;
}
@ -436,33 +433,33 @@ NS_IMETHODIMP nsMailboxUrl::SetQuery(const nsACString &aQuery)
// Assumption: attribute pairs in the string are separated by '&'.
char * extractAttributeValue(const char * searchString, const char * attributeName)
{
char * attributeValue = nsnull;
if (searchString && attributeName)
{
// search the string for attributeName
PRUint32 attributeNameSize = PL_strlen(attributeName);
char * startOfAttribute = PL_strcasestr(searchString, attributeName);
if (startOfAttribute)
{
startOfAttribute += attributeNameSize; // skip over the attributeName
if (startOfAttribute) // is there something after the attribute name
{
char * endofAttribute = startOfAttribute ? PL_strchr(startOfAttribute, '&') : nsnull;
if (startOfAttribute && endofAttribute) // is there text after attribute value
attributeValue = PL_strndup(startOfAttribute, endofAttribute - startOfAttribute);
else // there is nothing left so eat up rest of line.
attributeValue = PL_strdup(startOfAttribute);
// now unescape the string...
if (attributeValue)
attributeValue = nsUnescape(attributeValue); // unescape the string...
} // if we have a attribute value
} // if we have a attribute name
} // if we got non-null search string and attribute name values
return attributeValue;
char * attributeValue = nsnull;
if (searchString && attributeName)
{
// search the string for attributeName
PRUint32 attributeNameSize = PL_strlen(attributeName);
char * startOfAttribute = PL_strcasestr(searchString, attributeName);
if (startOfAttribute)
{
startOfAttribute += attributeNameSize; // skip over the attributeName
if (startOfAttribute) // is there something after the attribute name
{
char * endofAttribute = startOfAttribute ? PL_strchr(startOfAttribute, '&') : nsnull;
if (startOfAttribute && endofAttribute) // is there text after attribute value
attributeValue = PL_strndup(startOfAttribute, endofAttribute - startOfAttribute);
else // there is nothing left so eat up rest of line.
attributeValue = PL_strdup(startOfAttribute);
// now unescape the string...
if (attributeValue)
attributeValue = nsUnescape(attributeValue); // unescape the string...
} // if we have a attribute value
} // if we have a attribute name
} // if we got non-null search string and attribute name values
return attributeValue;
}
// nsIMsgI18NUrl support

View File

@ -132,12 +132,11 @@ NS_IMETHODIMP nsMsgMailboxParser::OnStartRequest(nsIRequest *request, nsISupport
m_graph_progress_total = dbName.GetFileSize();
UpdateStatusText(LOCAL_STATUS_SELECTING_MAILBOX);
nsCOMPtr<nsIMsgDatabase> mailDB;
rv = nsComponentManager::CreateInstance(kCMailDB, nsnull, NS_GET_IID(nsIMsgDatabase), (void **) getter_AddRefs(mailDB));
if (NS_SUCCEEDED(rv) && mailDB)
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
if (msgDBService)
{
//Use OpenFolderDB to always open the db so that db's m_folder is set correctly.
rv = mailDB->OpenFolderDB(folder, PR_TRUE, PR_TRUE, (nsIMsgDatabase **) getter_AddRefs(m_mailDB));
rv = msgDBService->OpenFolderDB(folder, PR_TRUE, PR_TRUE, (nsIMsgDatabase **) getter_AddRefs(m_mailDB));
if (m_mailDB)
m_mailDB->AddListener(this);
}
@ -1451,13 +1450,12 @@ nsParseNewMailState::Init(nsIMsgFolder *rootFolder, nsIMsgFolder *downloadFolder
// the new mail parser isn't going to get the stream input, it seems, so we can't use
// the OnStartRequest mechanism the mailbox parser uses. So, let's open the db right now.
nsCOMPtr<nsIMsgDatabase> mailDB;
rv = nsComponentManager::CreateInstance(kCMailDB, nsnull, NS_GET_IID(nsIMsgDatabase), (void **) getter_AddRefs(mailDB));
if (NS_SUCCEEDED(rv) && mailDB)
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
if (msgDBService)
{
nsCOMPtr <nsIFileSpec> dbFileSpec;
NS_NewFileSpecWithSpec(folder, getter_AddRefs(dbFileSpec));
rv = mailDB->OpenFolderDB(downloadFolder, PR_TRUE, PR_FALSE, (nsIMsgDatabase **) getter_AddRefs(m_mailDB));
rv = msgDBService->OpenFolderDB(downloadFolder, PR_TRUE, PR_FALSE, (nsIMsgDatabase **) getter_AddRefs(m_mailDB));
}
// rv = nsMailDatabase::Open(folder, PR_TRUE, &m_mailDB, PR_FALSE);
if (NS_FAILED(rv))

View File

@ -372,13 +372,13 @@ nsresult nsMsgNewsFolder::GetDatabase(nsIMsgWindow *aMsgWindow)
rv = GetPath(getter_AddRefs(pathSpec));
if (NS_FAILED(rv)) return rv;
nsCOMPtr <nsIMsgDatabase> newsDBFactory = do_CreateInstance(kCNewsDB, &rv);
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv,rv);
nsresult folderOpen = newsDBFactory->OpenFolderDB(this, PR_TRUE, PR_FALSE, getter_AddRefs(mDatabase));
nsresult folderOpen = msgDBService->OpenFolderDB(this, PR_TRUE, PR_FALSE, getter_AddRefs(mDatabase));
if(folderOpen == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING || folderOpen == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
folderOpen = newsDBFactory->OpenFolderDB(this, PR_TRUE, PR_TRUE, getter_AddRefs(mDatabase));
folderOpen = msgDBService->OpenFolderDB(this, PR_TRUE, PR_TRUE, getter_AddRefs(mDatabase));
if (NS_FAILED(folderOpen))
return folderOpen;