From 58acff1ca289342e498a7df9921174c5b8b2edb7 Mon Sep 17 00:00:00 2001 From: "bienvenu%nventure.com" Date: Wed, 20 Jul 2005 15:30:57 +0000 Subject: [PATCH] fix 295347 and 299346, duplicate entries in AB when dragging a card from another AB into a list, and lock file errors opening an AB causes us to create a backup AB as if the AB was corrupt, r=standard8, sr=mscott, a=asa --- .../addressbook/addressBook.properties | 3 + .../locale/en-US/addressBook.properties | 3 + mailnews/addrbook/src/nsAbMDBDirectory.cpp | 15 ++-- mailnews/addrbook/src/nsAbView.cpp | 2 +- mailnews/addrbook/src/nsAddrDatabase.cpp | 69 ++++++++++++------- mailnews/addrbook/src/nsAddrDatabase.h | 3 + 6 files changed, 62 insertions(+), 33 deletions(-) diff --git a/mail/locales/en-US/chrome/messenger/addressbook/addressBook.properties b/mail/locales/en-US/chrome/messenger/addressbook/addressBook.properties index 8420aab4557d..8a6c689c4aff 100644 --- a/mail/locales/en-US/chrome/messenger/addressbook/addressBook.properties +++ b/mail/locales/en-US/chrome/messenger/addressbook/addressBook.properties @@ -158,3 +158,6 @@ renameAddressBookTitle=Address Book Properties corruptMabFileTitle=Corrupt Address Book File corruptMabFileAlert=One of your address book files (%1$S file) could not be read. A new %2$S file will be created and a backup of the old file, called %3$S, will be created in the same directory. +# For locked .mab files +lockedMabFileTitle=Unable to Load Address Book File +lockedMabFileAlert=Unable to load address book file %S. It may be read-only, or locked by another application. Please try again later. diff --git a/mailnews/addrbook/resources/locale/en-US/addressBook.properties b/mailnews/addrbook/resources/locale/en-US/addressBook.properties index 969ecb82ea9b..9f084e508a79 100644 --- a/mailnews/addrbook/resources/locale/en-US/addressBook.properties +++ b/mailnews/addrbook/resources/locale/en-US/addressBook.properties @@ -159,3 +159,6 @@ renameAddressBookTitle=Address Book Properties corruptMabFileTitle=Corrupt Address Book File corruptMabFileAlert=One of your address book files (%1$S file) could not be read. A new %2$S file will be created and a backup of the old file, called %3$S, will be created in the same directory. +# For locked .mab files +lockedMabFileTitle=Unable to Load Address Book File +lockedMabFileAlert=Unable to load address book file %S. It may be read-only, or locked by another application. Please try again later. diff --git a/mailnews/addrbook/src/nsAbMDBDirectory.cpp b/mailnews/addrbook/src/nsAbMDBDirectory.cpp index b522329adb60..f259e711ea32 100644 --- a/mailnews/addrbook/src/nsAbMDBDirectory.cpp +++ b/mailnews/addrbook/src/nsAbMDBDirectory.cpp @@ -766,10 +766,7 @@ NS_IMETHODIMP nsAbMDBDirectory::DropCard(nsIAbCard* aCard, PRBool needToCopyCard * moz-abmdbdirectory://foo/bar */ NS_ENSURE_TRUE(mURI.Length() > kMDBDirectoryRootLen, NS_ERROR_UNEXPECTED); - if (strchr(mURI.get() + kMDBDirectoryRootLen, '/')) - mIsMailingList = 1; - else - mIsMailingList = 0; + mIsMailingList = (strchr(mURI.get() + kMDBDirectoryRootLen, '/')) ? 1 : 0; } if (!mDatabase) rv = GetAbDatabase(); @@ -800,8 +797,14 @@ NS_IMETHODIMP nsAbMDBDirectory::DropCard(nsIAbCard* aCard, PRBool needToCopyCard if (mIsMailingList == 1) { if (needToCopyCard) { - // first, add the card to the directory that contains the mailing list. - mDatabase->CreateNewCardAndAddToDB(newCard, PR_TRUE /* notify */); + nsCOMPtr cardRow; + // if card doesn't exist in db, add the card to the directory that + // contains the mailing list. + mDatabase->FindRowByCard(newCard, getter_AddRefs(cardRow)); + if (!cardRow) + mDatabase->CreateNewCardAndAddToDB(newCard, PR_TRUE /* notify */); + else + mDatabase->InitCardFromRow(newCard, cardRow); } // since we didn't copy the card, we don't have to notify that it was inserted mDatabase->CreateNewListCardAndAddToDB(this, m_dbRowID, newCard, PR_FALSE /* notify */); diff --git a/mailnews/addrbook/src/nsAbView.cpp b/mailnews/addrbook/src/nsAbView.cpp index f22ee90d7186..ec6df13719c9 100644 --- a/mailnews/addrbook/src/nsAbView.cpp +++ b/mailnews/addrbook/src/nsAbView.cpp @@ -506,7 +506,7 @@ nsresult nsAbView::RefreshTree() NS_IMETHODIMP nsAbView::GetCellText(PRInt32 row, nsITreeColumn* col, nsAString& _retval) { - NS_ENSURE_TRUE(row >= 0, NS_ERROR_UNEXPECTED); + NS_ENSURE_TRUE(row >= 0 && row < mCards.Count(), NS_ERROR_UNEXPECTED); nsIAbCard *card = ((AbCard *)(mCards.ElementAt(row)))->card; // XXX fix me by converting GetCardValue to take an nsAString& diff --git a/mailnews/addrbook/src/nsAddrDatabase.cpp b/mailnews/addrbook/src/nsAddrDatabase.cpp index 91209db634d4..9ae8f027d979 100644 --- a/mailnews/addrbook/src/nsAddrDatabase.cpp +++ b/mailnews/addrbook/src/nsAddrDatabase.cpp @@ -572,10 +572,22 @@ NS_IMETHODIMP nsAddrDatabase::Open if (NS_SUCCEEDED(rv)) return NS_OK; + if (rv == NS_ERROR_FILE_ACCESS_DENIED) + { + static PRBool gAlreadyAlerted; + // only do this once per session to avoid annoying the user + if (!gAlreadyAlerted) + { + gAlreadyAlerted = PR_TRUE; + nsXPIDLCString mabFileName; + mabFileName.Adopt(mabFileSpec.GetLeafName()); + AlertAboutLockedMabFile(NS_ConvertASCIItoUCS2(mabFileName).get()); + } + } // try one more time // but first rename corrupt mab file // and prompt the user - if (aCreate) + else if (aCreate) { nsFileSpec *newMabFile = new nsFileSpec(mabFileSpec); if (!newMabFile) @@ -617,7 +629,7 @@ NS_IMETHODIMP nsAddrDatabase::Open return rv; } -nsresult nsAddrDatabase::AlertAboutCorruptMabFile(const PRUnichar *aOldFileName, const PRUnichar *aNewFileName) +nsresult nsAddrDatabase::DisplayAlert(const PRUnichar *titleName, const PRUnichar *alertStringName, const PRUnichar **formatStrings, PRInt32 numFormatStrings) { nsresult rv; nsCOMPtr bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); @@ -626,26 +638,35 @@ nsresult nsAddrDatabase::AlertAboutCorruptMabFile(const PRUnichar *aOldFileName, nsCOMPtr bundle; rv = bundleService->CreateBundle("chrome://messenger/locale/addressbook/addressBook.properties", getter_AddRefs(bundle)); NS_ENSURE_SUCCESS(rv, rv); - - const PRUnichar *formatStrings[] = { aOldFileName, aOldFileName, aNewFileName }; nsXPIDLString alertMessage; - rv = bundle->FormatStringFromName(NS_LITERAL_STRING("corruptMabFileAlert").get(), - formatStrings, 3, + rv = bundle->FormatStringFromName(alertStringName, formatStrings, numFormatStrings, getter_Copies(alertMessage)); NS_ENSURE_SUCCESS(rv, rv); nsXPIDLString alertTitle; - rv = bundle->GetStringFromName(NS_LITERAL_STRING("corruptMabFileTitle").get(), getter_Copies(alertTitle)); + rv = bundle->GetStringFromName(titleName, getter_Copies(alertTitle)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr prompter = do_GetService(NS_PROMPTSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); - rv = prompter->Alert(nsnull /* we don't know the parent window */, alertTitle.get(), alertMessage.get()); - NS_ENSURE_SUCCESS(rv, rv); - return NS_OK; + return prompter->Alert(nsnull /* we don't know the parent window */, alertTitle.get(), alertMessage.get()); +} + +nsresult nsAddrDatabase::AlertAboutCorruptMabFile(const PRUnichar *aOldFileName, const PRUnichar *aNewFileName) +{ + const PRUnichar *formatStrings[] = { aOldFileName, aOldFileName, aNewFileName }; + return DisplayAlert(NS_LITERAL_STRING("corruptMabFileTitle").get(), + NS_LITERAL_STRING("corruptMabFileAlert").get(), formatStrings, 3); +} + +nsresult nsAddrDatabase::AlertAboutLockedMabFile(const PRUnichar *aFileName) +{ + const PRUnichar *formatStrings[] = { aFileName }; + return DisplayAlert(NS_LITERAL_STRING("lockedMabFileTitle").get(), + NS_LITERAL_STRING("lockedMabFileAlert").get(), formatStrings, 1); } nsresult @@ -710,6 +731,7 @@ NS_IMETHODIMP nsAddrDatabase::OpenMDB(nsFileSpec *dbName, PRBool create) mdb_bool canOpen; mdbYarn outFormatVersion; nsIMdbFile* oldFile = 0; + PRBool isEmptyFile = !dbName->GetFileSize(); ret = myMDBFactory->OpenOldFile(m_mdbEnv, dbHeap, nativeFileName, dbFrozen, &oldFile); @@ -728,11 +750,13 @@ NS_IMETHODIMP nsAddrDatabase::OpenMDB(nsFileSpec *dbName, PRBool create) ret = myMDBFactory->OpenFileStore(m_mdbEnv, dbHeap, oldFile, &inOpenPolicy, &thumb); } - else - ret = NS_ERROR_FAILURE; //check: use the right error code + else if (!isEmptyFile) + ret = NS_ERROR_FILE_ACCESS_DENIED; } NS_RELEASE(oldFile); // always release our file ref, store has own } + if (NS_FAILED(ret)) + ret = NS_ERROR_FILE_ACCESS_DENIED; } nsCRT::free(nativeFileName); @@ -763,7 +787,7 @@ NS_IMETHODIMP nsAddrDatabase::OpenMDB(nsFileSpec *dbName, PRBool create) } } } - else if (create) // ### need error code saying why open file store failed + else if (create && ret != NS_ERROR_FILE_ACCESS_DENIED) { nsIMdbFile* newFile = 0; ret = myMDBFactory->CreateNewFile(m_mdbEnv, dbHeap, dbName->GetCString(), &newFile); @@ -1570,7 +1594,7 @@ NS_IMETHODIMP nsAddrDatabase::CreateNewCardAndAddToDBWithKey(nsIAbCard *newCard, NS_IMETHODIMP nsAddrDatabase::CreateNewListCardAndAddToDB(nsIAbDirectory *aList, PRUint32 listRowID, nsIAbCard *newCard, PRBool notify /* = FALSE */) { - if (!newCard || !m_mdbPabTable) + if (!newCard || !m_mdbPabTable) return NS_ERROR_NULL_POINTER; nsIMdbRow* pListRow = nsnull; @@ -1865,16 +1889,16 @@ NS_IMETHODIMP nsAddrDatabase::CreateMailListAndAddToDB(nsIAbDirectory *newList, void nsAddrDatabase::DeleteCardFromAllMailLists(mdb_id cardRowID) { - nsIMdbTableRowCursor* rowCursor; - m_mdbPabTable->GetTableRowCursor(GetEnv(), -1, &rowCursor); + nsCOMPtr rowCursor; + m_mdbPabTable->GetTableRowCursor(GetEnv(), -1, getter_AddRefs(rowCursor)); if (rowCursor) { - nsIMdbRow* pListRow = nsnull; + nsCOMPtr pListRow; mdb_pos rowPos; do { - mdb_err err = rowCursor->NextRow(GetEnv(), &pListRow, &rowPos); + mdb_err err = rowCursor->NextRow(GetEnv(), getter_AddRefs(pListRow), &rowPos); if (err == NS_OK && pListRow) { @@ -1885,11 +1909,8 @@ void nsAddrDatabase::DeleteCardFromAllMailLists(mdb_id cardRowID) if (IsListRowScopeToken(rowOid.mOid_Scope)) DeleteCardFromListRow(pListRow, cardRowID); } - NS_RELEASE(pListRow); } } while (pListRow); - - rowCursor->Release(); } } @@ -1946,10 +1967,6 @@ nsresult nsAddrDatabase::DeleteCardFromListRow(nsIMdbRow* pListRow, mdb_id cardR nsresult err = NS_OK; -// PRUint32 cardRowID; -// card->GetDbRowID(&cardRowID); - - //todo: cut the card column and total column PRUint32 totalAddress = GetListAddressTotal(pListRow); PRUint32 pos; @@ -3701,7 +3718,7 @@ nsAddrDatabase::HasRowButDeletedForCharColumn(const PRUnichar *unicodeStr, mdb_c // if still no deleted cards table, there are no deleted cards if (!m_mdbDeletedCardsTable) - return PR_TRUE; + return PR_FALSE; mdb_bool hasRow = PR_FALSE; rv = m_mdbDeletedCardsTable->HasRow(env, *aFindRow, &hasRow); diff --git a/mailnews/addrbook/src/nsAddrDatabase.h b/mailnews/addrbook/src/nsAddrDatabase.h index 73a0b7780765..69dbd576ac48 100644 --- a/mailnews/addrbook/src/nsAddrDatabase.h +++ b/mailnews/addrbook/src/nsAddrDatabase.h @@ -477,6 +477,9 @@ private: PRBool HasRowButDeletedForCharColumn(const PRUnichar *unicodeStr, mdb_column findColumn, PRBool aIsCard, nsIMdbRow **aFindRow); nsresult OpenInternal(nsFileSpec *aMabFile, PRBool aCreate, nsIAddrDatabase **pCardDB); nsresult AlertAboutCorruptMabFile(const PRUnichar *aOldFileName, const PRUnichar *aNewFileName); + nsresult AlertAboutLockedMabFile(const PRUnichar *aFileName); + nsresult DisplayAlert(const PRUnichar *titleName, const PRUnichar *alertStringName, + const PRUnichar **formatStrings, PRInt32 numFormatStrings); }; #endif