fix 266536 handling of out of date local folder summary files, sr=mscott

git-svn-id: svn://10.0.0.236/trunk@164609 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
bienvenu%nventure.com
2004-10-29 18:20:14 +00:00
parent 2b29cb75ff
commit ad51f9a2c6
6 changed files with 154 additions and 54 deletions

View File

@@ -255,7 +255,7 @@ function OnUnloadMsgHeaderPane()
var messageHeaderSink = {
onStartHeaders: function()
{
mSaveHdr = null;
// clear out any pending collected address timers...
if (gCollectAddressTimer)
{
@@ -374,6 +374,20 @@ var messageHeaderSink = {
handleAttachment: function(contentType, url, displayName, uri, notDownloaded)
{
// presentation level change....don't show vcards as external attachments in the UI.
// libmime already renders them inline.
if (contentType == "text/x-vcard")
{
var inlineAttachments = pref.getBoolPref("mail.inline_attachments");
var displayHtmlAs = pref.getIntPref("mailnews.display.html_as");
if (inlineAttachments && !displayHtmlAs)
{
mSaveHdr = messenger.messageServiceFromURI(uri).messageURIToMsgHdr(uri);
return;
}
}
currentAttachments.push (new createNewAttachmentInfo(contentType, url, displayName, uri, notDownloaded));
// if we have an attachment, set the MSG_FLAG_ATTACH flag on the hdr
// this will cause the "message with attachment" icon to show up
@@ -399,6 +413,11 @@ var messageHeaderSink = {
onEndAllAttachments: function()
{
// if we only got a v-card, turn off the attachments flag
if (!currentAttachments.length && mSaveHdr)
mSaveHdr.markHasAttachments(false);
mSaveHdr = null;
displayAttachmentsForExpandedView();
// AddSaveAllAttachmentsMenu();
if (gCollapsedHeaderViewMode)
displayAttachmentsForCollapsedView();
@@ -420,6 +439,7 @@ var messageHeaderSink = {
},
mSecurityInfo : null,
mSaveHdr: null,
getSecurityInfo: function()
{
return this.mSecurityInfo;

View File

@@ -115,7 +115,7 @@ nsMsgDBService::~nsMsgDBService()
{
}
NS_IMETHODIMP nsMsgDBService::OpenFolderDB(nsIMsgFolder *aFolder, PRBool aCreate, PRBool aUpgrading, nsIMsgDatabase **_retval)
NS_IMETHODIMP nsMsgDBService::OpenFolderDB(nsIMsgFolder *aFolder, PRBool aCreate, PRBool aLeaveInvalidDB, nsIMsgDatabase **_retval)
{
NS_ENSURE_ARG(aFolder);
*_retval = nsMsgDatabase::FindInCache(aFolder);
@@ -134,7 +134,7 @@ NS_IMETHODIMP nsMsgDBService::OpenFolderDB(nsIMsgFolder *aFolder, PRBool aCreate
nsCOMPtr <nsIFileSpec> folderPath;
rv = aFolder->GetPath(getter_AddRefs(folderPath));
NS_ENSURE_SUCCESS(rv, rv);
rv = msgDB->Open(folderPath, aCreate, aUpgrading);
rv = msgDB->Open(folderPath, aCreate, aLeaveInvalidDB);
if (NS_FAILED(rv) && (rv != NS_MSG_ERROR_FOLDER_SUMMARY_MISSING
&& rv != NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE || !aCreate))
return rv;
@@ -167,7 +167,7 @@ NS_IMETHODIMP nsMsgDBService::OpenFolderDB(nsIMsgFolder *aFolder, PRBool aCreate
return rv;
}
NS_IMETHODIMP nsMsgDBService::OpenMailDBFromFileSpec(nsIFileSpec *aFolderName, PRBool aCreate, PRBool aUpgrading, nsIMsgDatabase** pMessageDB)
NS_IMETHODIMP nsMsgDBService::OpenMailDBFromFileSpec(nsIFileSpec *aFolderName, PRBool aCreate, PRBool aLeaveInvalidDB, nsIMsgDatabase** pMessageDB)
{
nsFileSpec folderName;
@@ -184,7 +184,7 @@ NS_IMETHODIMP nsMsgDBService::OpenMailDBFromFileSpec(nsIFileSpec *aFolderName, P
nsresult rv;
nsCOMPtr <nsIMsgDatabase> msgDB = do_CreateInstance(NS_MAILBOXDB_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = msgDB->Open(aFolderName, aCreate, aUpgrading);
rv = msgDB->Open(aFolderName, aCreate, aLeaveInvalidDB);
NS_IF_ADDREF(*pMessageDB = msgDB);
if (aCreate && msgDB && rv == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
rv = NS_OK;
@@ -1055,10 +1055,10 @@ void nsMsgDatabase::UnixToNative(char*& ioPath)
#endif /* XP_MAC */
// caller passes in upgrading==PR_TRUE if they want back a db even if the db is out of date.
// caller passes in leaveInvalidDB==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_IMETHODIMP nsMsgDatabase::Open(nsIFileSpec *aFolderName, PRBool aCreate, PRBool aLeaveInvalidDB)
{
PRBool summaryFileExists;
PRBool newFile = PR_FALSE;
@@ -1075,7 +1075,7 @@ NS_IMETHODIMP nsMsgDatabase::Open(nsIFileSpec *aFolderName, PRBool aCreate, PRBo
#if defined(DEBUG_bienvenu)
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);
this, aLeaveInvalidDB ? "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)
@@ -1113,7 +1113,7 @@ NS_IMETHODIMP nsMsgDatabase::Open(nsIFileSpec *aFolderName, PRBool aCreate, PRBo
err = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
NS_RELEASE(folderInfo);
}
if (NS_FAILED(err) && !aUpgrading)
if (NS_FAILED(err) && !aLeaveInvalidDB)
deleteInvalidDB = PR_TRUE;
}
else
@@ -1134,11 +1134,11 @@ NS_IMETHODIMP nsMsgDatabase::Open(nsIFileSpec *aFolderName, PRBool aCreate, PRBo
{
// 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,
if (newFile && !aLeaveInvalidDB) // 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)
else if (err != NS_OK && err != NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
{
Close(PR_FALSE);
summarySpec.Delete(PR_FALSE); // blow away the db if it's corrupt.

View File

@@ -57,7 +57,7 @@ struct nsLocalFolderScanState;
%}
[scriptable, uuid(b8e26003-f2bb-4239-ba47-d597ab6e3671)]
[scriptable, uuid(94bf4be7-4af2-462b-a7cc-c4298c335829)]
interface nsIMsgLocalMailFolder : nsISupports {
/**
* set the default flags on the subfolders of this folder, such as
@@ -67,7 +67,17 @@ interface nsIMsgLocalMailFolder : nsISupports {
* like MSG_FOLDER_FLAG_INBOX | MSG_FOLDER_FLAG_DRAFTS | etc
*/
void setFlagsOnDefaultMailboxes(in unsigned long flags);
/*
* This will return null if the db is out of date
*/
nsIMsgDatabase getDatabaseWOReparse();
/*
* This will kick off a url to reparse the db if it's out of date.
* If aReparseUrlListener isn ull, folder will use itself as the listener
*/
nsIMsgDatabase getDatabaseWithReparse(in nsIUrlListener aReparseUrlListener, in nsIMsgWindow aMsgWindow);
void parseFolder(in nsIMsgWindow aMsgWindow, in nsIUrlListener listener);
void copyFolderLocal(in nsIMsgFolder srcFolder, in boolean isMove, in nsIMsgWindow msgWindow, in nsIMsgCopyServiceListener listener );
void copyAllSubFolders(in nsIMsgFolder srcFolder, in nsIMsgWindow msgWindow, in nsIMsgCopyServiceListener listener );

View File

@@ -338,31 +338,15 @@ NS_IMETHODIMP nsMsgLocalMailFolder::ParseFolder(nsIMsgWindow *aMsgWindow, nsIUrl
return rv;
}
//we treat failure as null db returned
NS_IMETHODIMP nsMsgLocalMailFolder::GetDatabaseWOReparse(nsIMsgDatabase **aDatabase)
// this won't force a reparse of the folder if the db is invalid.
NS_IMETHODIMP
nsMsgLocalMailFolder::GetMsgDatabase(nsIMsgWindow *aMsgWindow,
nsIMsgDatabase** aMsgDatabase)
{
nsresult rv=NS_OK;
NS_ENSURE_ARG(aDatabase);
if (!mDatabase)
{
nsCOMPtr <nsIFileSpec> destIFolderSpec;
rv = GetPath(getter_AddRefs(destIFolderSpec));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && msgDBService)
{
rv = msgDBService->OpenFolderDB(this, PR_FALSE, PR_FALSE, (nsIMsgDatabase **) getter_AddRefs(mDatabase));
if (mDatabase && NS_SUCCEEDED(rv))
mDatabase->AddListener(this);
}
}
*aDatabase = mDatabase;
NS_IF_ADDREF(*aDatabase);
return rv;
return GetDatabaseWOReparse(aMsgDatabase);
}
NS_IMETHODIMP
nsMsgLocalMailFolder::Enumerate(nsIEnumerator* *result)
{
@@ -477,12 +461,55 @@ nsMsgLocalMailFolder::GetSubFolders(nsIEnumerator* *result)
return rv;
}
//Makes sure the database is open and exists. If the database is valid then
//returns NS_OK. Otherwise returns a failure error value.
nsresult nsMsgLocalMailFolder::GetDatabase(nsIMsgWindow *aMsgWindow)
{
return GetDatabaseWOReparse(getter_AddRefs(mDatabase));
}
//we treat failure as null db returned
NS_IMETHODIMP nsMsgLocalMailFolder::GetDatabaseWOReparse(nsIMsgDatabase **aDatabase)
{
nsresult rv=NS_OK;
if (m_parsingFolder)
return NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
NS_ENSURE_ARG(aDatabase);
if (!mDatabase)
{
nsCOMPtr <nsIFileSpec> destIFolderSpec;
rv = GetPath(getter_AddRefs(destIFolderSpec));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && msgDBService)
{
rv = msgDBService->OpenFolderDB(this, PR_FALSE, PR_TRUE, (nsIMsgDatabase **) getter_AddRefs(mDatabase));
if (mDatabase && NS_SUCCEEDED(rv))
mDatabase->AddListener(this);
}
}
*aDatabase = mDatabase;
NS_IF_ADDREF(*aDatabase);
return rv;
}
// Makes sure the database is open and exists. If the database is out of date,
// then this call will run an async url to reparse the folder. The passed in
// url listener will get called when the url is done.
NS_IMETHODIMP nsMsgLocalMailFolder::GetDatabaseWithReparse(nsIUrlListener *aReparseUrlListener, nsIMsgWindow *aMsgWindow,
nsIMsgDatabase **aMsgDatabase)
{
nsresult rv = NS_OK;
// if we're already reparsing, just remember the listener so we can notify it
// when we've finished.
if (m_parsingFolder)
{
NS_ASSERTION(!mReparseListener, "can't have an existing listener");
mReparseListener = aReparseUrlListener;
return NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
}
if (!mDatabase)
{
nsCOMPtr<nsIFileSpec> pathSpec;
@@ -548,7 +575,7 @@ nsresult nsMsgLocalMailFolder::GetDatabase(nsIMsgWindow *aMsgWindow)
if(folderOpen == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING ||
folderOpen == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
{
if(NS_FAILED(rv = ParseFolder(aMsgWindow, this)))
if(NS_FAILED(rv = ParseFolder(aMsgWindow, (aReparseUrlListener) ? aReparseUrlListener : this)))
{
if (rv == NS_MSG_FOLDER_BUSY)
{
@@ -568,6 +595,7 @@ nsresult nsMsgLocalMailFolder::GetDatabase(nsIMsgWindow *aMsgWindow)
}
}
}
NS_IF_ADDREF(*aMsgDatabase = mDatabase);
return rv;
}
@@ -616,7 +644,7 @@ nsMsgLocalMailFolder::UpdateFolder(nsIMsgWindow *aWindow)
//If we don't currently have a database, get it. Otherwise, the folder has been updated (presumably this
//changes when we download headers when opening inbox). If it's updated, send NotifyFolderLoaded.
if(!mDatabase)
rv = GetDatabase(aWindow); // this will cause a reparse, if needed.
rv = GetDatabaseWithReparse(this, aWindow, getter_AddRefs(mDatabase));
else
{
PRBool valid;
@@ -644,7 +672,7 @@ nsMsgLocalMailFolder::UpdateFolder(nsIMsgWindow *aWindow)
NS_IMETHODIMP
nsMsgLocalMailFolder::GetMessages(nsIMsgWindow *aMsgWindow, nsISimpleEnumerator* *result)
{
nsresult rv = GetDatabase(aMsgWindow);
nsresult rv = GetDatabaseWOReparse(getter_AddRefs(mDatabase));
if(NS_SUCCEEDED(rv))
return mDatabase->EnumerateMessages(result);
@@ -1450,7 +1478,7 @@ nsMsgLocalMailFolder::DeleteMessages(nsISupportsArray *messages,
}
else
{
rv = GetDatabase(msgWindow);
rv = GetDatabaseWOReparse(getter_AddRefs(mDatabase));
if(NS_SUCCEEDED(rv))
{
nsCOMPtr<nsISupports> msgSupport;
@@ -1497,7 +1525,7 @@ nsMsgLocalMailFolder::InitCopyState(nsISupports* aSupport,
return NS_ERROR_FAILURE; // already has a copy in progress
// get mDatabase set, so we can use it to add new hdrs to this db.
// calling GetDatabaseWOReparse will set mDatabase - we use the comptr
// calling GetDatabase will set mDatabase - we use the comptr
// here to avoid doubling the refcnt on mDatabase. We don't care if this
// fails - we just want to give it a chance. It will definitely fail in
// nsLocalMailFolder::EndCopy because we will have written data to the folder
@@ -1888,6 +1916,12 @@ nsMsgLocalMailFolder::CopyFolderLocal(nsIMsgFolder *srcFolder, PRBool isMoveFold
srcFolder->GetName(getter_Copies(folderName));
nsAutoString safeFolderName(folderName);
NS_MsgHashIfNecessary(safeFolderName);
nsCOMPtr <nsIMsgLocalMailFolder> localFolder = do_QueryInterface(srcFolder);
nsCOMPtr <nsIMsgDatabase> srcDB;
if (localFolder)
localFolder->GetDatabaseWOReparse(getter_AddRefs(srcDB));
PRBool summaryValid = (srcDB != nsnull);
srcDB = nsnull;
srcFolder->ForceDBClosed();
nsCOMPtr<nsIFileSpec> oldPathSpec;
@@ -1926,6 +1960,25 @@ nsMsgLocalMailFolder::CopyFolderLocal(nsIMsgFolder *srcFolder, PRBool isMoveFold
rv = summarySpec.CopyToDir(newPath);
NS_ENSURE_SUCCESS(rv, rv);
// linux and mac are not good about maintaining the file stamp when copying folders
// around. So if the source folder db is good, set the dest db as good too.
nsCOMPtr <nsIMsgDatabase> destDB;
if (summaryValid)
{
nsCAutoString folderLeafName;
folderLeafName.Adopt(path.GetLeafName());
newPath += folderLeafName.get();
nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && msgDBService)
{
nsCOMPtr <nsIFileSpec> dbFileSpec;
NS_NewFileSpecWithSpec(newPath, getter_AddRefs(dbFileSpec));
rv = msgDBService->OpenMailDBFromFileSpec(dbFileSpec, PR_FALSE, PR_TRUE, getter_AddRefs(destDB));
if ((NS_SUCCEEDED(rv) || rv == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE) && destDB)
destDB->SetSummaryValid(PR_TRUE);
// destDB->Close(PR_TRUE);
}
}
rv = AddSubfolder(safeFolderName, getter_AddRefs(newMsgFolder));
NS_ENSURE_SUCCESS(rv, rv);
@@ -2103,7 +2156,8 @@ NS_IMETHODIMP nsMsgLocalMailFolder::GetNewMessages(nsIMsgWindow *aWindow, nsIUrl
{
PRBool valid = PR_FALSE;
nsCOMPtr <nsIMsgDatabase> db;
rv = inbox->GetMsgDatabase(aWindow, getter_AddRefs(db));
// this will kick off a reparse if the db is out of date.
rv = localInbox->GetDatabaseWithReparse(nsnull, aWindow, getter_AddRefs(db));
if (NS_SUCCEEDED(rv) && db)
{
rv = db->GetSummaryValid(&valid);
@@ -3191,6 +3245,11 @@ nsMsgLocalMailFolder::OnStopRunningUrl(nsIURI * aUrl, nsresult aExitCode)
}
}
if (m_parsingFolder && mReparseListener)
{
mReparseListener->OnStopRunningUrl(aUrl, aExitCode);
mReparseListener = nsnull;
}
m_parsingFolder = PR_FALSE;
return nsMsgDBFolder::OnStopRunningUrl(aUrl, aExitCode);
}

View File

@@ -138,6 +138,8 @@ public:
// nsIMsgFolder methods:
NS_IMETHOD GetSubFolders(nsIEnumerator* *result);
NS_IMETHODIMP GetMsgDatabase(nsIMsgWindow *aMsgWindow,
nsIMsgDatabase** aMsgDatabase);
NS_IMETHOD GetMessages(nsIMsgWindow *aMsgWindow, nsISimpleEnumerator* *result);
NS_IMETHOD UpdateFolder(nsIMsgWindow *aWindow);
@@ -199,7 +201,6 @@ protected:
nsresult CopyFolderAcrossServer(nsIMsgFolder *srcFolder, nsIMsgWindow *msgWindow,nsIMsgCopyServiceListener* listener);
nsresult CreateSubFolders(nsFileSpec &path);
nsresult GetDatabase(nsIMsgWindow *aMsgWindow);
nsresult GetTrashFolder(nsIMsgFolder** trashFolder);
nsresult WriteStartOfNewMessage();
nsresult IsChildOfTrash(PRBool *result);
@@ -208,6 +209,7 @@ protected:
nsresult DeleteMessage(nsISupports *message, nsIMsgWindow *msgWindow,
PRBool deleteStorage, PRBool commit);
nsresult GetDatabase(nsIMsgWindow *msgWindow);
// copy message helper
nsresult DisplayMoveCopyStatusMsg();
@@ -235,6 +237,7 @@ protected:
PRPackedBool mCheckForNewMessagesAfterParsing;
PRPackedBool m_parsingFolder;
nsCOMPtr<nsIMsgStringService> mMsgStringService;
nsCOMPtr<nsIUrlListener> mReparseListener;
PRInt32 mNumFilterClassifyRequests;
nsMsgKeyArray mSpamKeysToMove;
nsCString mSpamFolderURI;

View File

@@ -302,19 +302,15 @@ nsresult nsPop3IncomingServer::GetInbox(nsIMsgWindow *msgWindow, nsIMsgFolder **
nsCOMPtr<nsIMsgLocalMailFolder> localInbox = do_QueryInterface(*inbox, &rv);
if (NS_SUCCEEDED(rv) && localInbox)
{
PRBool valid = PR_FALSE;
nsCOMPtr <nsIMsgDatabase> db;
rv = (*inbox)->GetMsgDatabase(msgWindow, getter_AddRefs(db));
if (NS_SUCCEEDED(rv) && db)
if (NS_FAILED(rv))
{
rv = db->GetSummaryValid(&valid);
if (!valid)
{
(*inbox)->SetMsgDatabase(nsnull);
(void) localInbox->SetCheckForNewMessagesAfterParsing(PR_TRUE);
(*inbox)->GetMsgDatabase(msgWindow, getter_AddRefs(db));
return NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
}
(*inbox)->SetMsgDatabase(nsnull);
(void) localInbox->SetCheckForNewMessagesAfterParsing(PR_TRUE);
// this will cause a reparse of the mail folder.
localInbox->GetDatabaseWithReparse(nsnull, msgWindow, getter_AddRefs(db));
return NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
}
}
return rv;
@@ -631,6 +627,18 @@ nsresult nsPop3GetMailChainer::GetNewMailForServers(nsISupportsArray *servers, n
m_folderToDownloadTo = folderToDownloadTo;
m_downloadingMsgWindow = msgWindow;
m_listener = listener;
nsCOMPtr <nsIMsgDatabase> destFolderDB;
nsresult rv = folderToDownloadTo->GetMsgDatabase(msgWindow, getter_AddRefs(destFolderDB));
if (NS_FAILED(rv) || !destFolderDB)
{
nsCOMPtr <nsIMsgLocalMailFolder> localFolder = do_QueryInterface(folderToDownloadTo);
if (localFolder)
{
localFolder->GetDatabaseWithReparse(this, msgWindow, getter_AddRefs(destFolderDB));
return NS_OK;
}
}
return RunNextGetNewMail();
}