diff --git a/mailnews/addrbook/public/nsIAddressBook.idl b/mailnews/addrbook/public/nsIAddressBook.idl index 02a1845df49..df6db3e9f97 100644 --- a/mailnews/addrbook/public/nsIAddressBook.idl +++ b/mailnews/addrbook/public/nsIAddressBook.idl @@ -32,6 +32,7 @@ %} interface nsIDOMWindow; +interface nsIFileSpec; [scriptable, uuid(D60B84F1-2A8C-11d3-9E07-00A0C92B5F0D)] interface nsIAddressBook : nsISupports { @@ -43,5 +44,6 @@ interface nsIAddressBook : nsISupports { void printAddressbook(); void setWebShellWindow(in nsIDOMWindow win); void importAddressBook(); + void convertLDIFtoMAB(in nsIFileSpec fileSpec); }; diff --git a/mailnews/addrbook/src/nsAddressBook.cpp b/mailnews/addrbook/src/nsAddressBook.cpp index 19a087fa5f9..1c8665deb6d 100644 --- a/mailnews/addrbook/src/nsAddressBook.cpp +++ b/mailnews/addrbook/src/nsAddressBook.cpp @@ -348,7 +348,7 @@ class AddressBookParser protected: nsCAutoString mLine; - nsIFileSpecWithUI* mFileSpec; + nsCOMPtr mFileSpec; char* mDbUri; nsCOMPtr mDatabase; PRInt32 mFileType; @@ -364,13 +364,13 @@ protected: char * str_getline( char **next ); public: - AddressBookParser(nsIFileSpecWithUI* fileSpec); + AddressBookParser(nsIFileSpec *fileSpec); ~AddressBookParser(); nsresult ParseFile(); }; -AddressBookParser::AddressBookParser(nsIFileSpecWithUI* fileSpec) +AddressBookParser::AddressBookParser(nsIFileSpec * fileSpec) { mFileSpec = fileSpec; mDbUri = nsnull; @@ -397,8 +397,7 @@ nsresult AddressBookParser::ParseFile() /* Get database file name */ char *leafName = nsnull; nsString fileString; - if (mFileSpec) - { + if (mFileSpec) { mFileSpec->GetLeafName(&leafName); fileString = leafName; if (-1 != fileString.Find(kTabExtension) || -1 != fileString.Find(kTxtExtension)) @@ -1249,6 +1248,23 @@ void AddressBookParser::AddLdifColToDatabase(nsIMdbRow* newRow, char* typeSlot, } } +NS_IMETHODIMP nsAddressBook::ConvertLDIFtoMAB(nsIFileSpec *fileSpec) +{ + nsresult rv; + if (!fileSpec) return NS_ERROR_FAILURE; + + rv = fileSpec->OpenStreamForReading(); + if (NS_FAILED(rv)) return rv; + + AddressBookParser abParser(fileSpec); + + rv = abParser.ParseFile(); + if (NS_FAILED(rv)) return rv; + + rv = fileSpec->CloseStream(); + return rv; +} + NS_IMETHODIMP nsAddressBook::ImportAddressBook() { nsresult rv = NS_ERROR_FAILURE; @@ -1257,20 +1273,13 @@ NS_IMETHODIMP nsAddressBook::ImportAddressBook() if (!fileSpec) return NS_ERROR_FAILURE; - rv = fileSpec->ChooseInputFile( - "Open File", nsIFileSpecWithUI::eAllFiles, nsnull, nsnull); + // XXX: todo "Open File" should be in a string bundle + rv = fileSpec->ChooseInputFile("Open File", nsIFileSpecWithUI::eAllFiles, nsnull, nsnull); if (NS_FAILED(rv)) return rv; - rv = fileSpec->OpenStreamForReading(); - if (NS_SUCCEEDED(rv)) - { - AddressBookParser abParser(fileSpec); - rv = abParser.ParseFile(); - rv = fileSpec->CloseStream(); - } - - return rv; + rv = ConvertLDIFtoMAB(fileSpec); + return rv; } CMDLINEHANDLER_IMPL(nsAddressBook,"-addressbook","general.startup.addressbook","chrome://addressbook/content/","Start with the addressbook.",NS_ADDRESSBOOKSTARTUPHANDLER_PROGID,"Addressbook Startup Handler",PR_FALSE,"", PR_TRUE) diff --git a/mailnews/addrbook/src/nsDirPrefs.cpp b/mailnews/addrbook/src/nsDirPrefs.cpp index 0f1fe89ed7b..106835324bf 100644 --- a/mailnews/addrbook/src/nsDirPrefs.cpp +++ b/mailnews/addrbook/src/nsDirPrefs.cpp @@ -415,7 +415,7 @@ static nsresult dir_ConvertToMabFileName() PRInt32 pos = name.Find(ABFileName_kPreviousSuffix); if (pos > 0) { - //Move old abook.na2 to end of the list anf change the description + //Move old abook.na2 to end of the list and change the description DIR_Server * newServer = nsnull; DIR_CopyServer(server, &newServer); newServer->position = count + 1; @@ -3422,7 +3422,10 @@ nsresult DIR_GetServerPreferences(nsVoidArray** list) if (version < kCurrentListVersion) { pPref->SetIntPref(PREF_LDAP_VERSION_NAME, kCurrentListVersion); + // not needed, we do ab conversion now +#if 0 dir_ConvertToMabFileName(); +#endif } /* Write the merged list so we get it next time we ask */ if (savePrefs) diff --git a/mailnews/base/src/nsMessengerMigrator.cpp b/mailnews/base/src/nsMessengerMigrator.cpp index 7170116da98..89cf744d932 100644 --- a/mailnews/base/src/nsMessengerMigrator.cpp +++ b/mailnews/base/src/nsMessengerMigrator.cpp @@ -60,7 +60,9 @@ #include "nsEscape.h" #include "nsIUserInfo.h" - +#include "nsIAbUpgrader.h" +#include "nsIAddressBook.h" +#include "nsAbBaseCID.h" #define BUF_STR_LEN 1024 @@ -77,6 +79,8 @@ static NS_DEFINE_CID(kSmtpServiceCID, NS_SMTPSERVICE_CID); static NS_DEFINE_CID(kFileLocatorCID, NS_FILELOCATOR_CID); static NS_DEFINE_CID(kMsgAccountManagerCID, NS_MSGACCOUNTMANAGER_CID); static NS_DEFINE_IID(kIFileLocatorIID, NS_IFILELOCATOR_IID); +static NS_DEFINE_CID(kAB4xUpgraderServiceCID, NS_AB4xUPGRADER_CID); +static NS_DEFINE_CID(kAddressBookCID, NS_ADDRESSBOOK_CID); #define IMAP_SCHEMA "imap:/" #define IMAP_SCHEMA_LENGTH 6 @@ -673,6 +677,9 @@ nsMessengerMigrator::UpgradePrefs() rv = MigrateNewsAccounts(identity); if (NS_FAILED(rv)) return rv; + rv = MigrateAddressBooks(); + if (NS_FAILED(rv)) return rv; + // we're done migrating, let's save the prefs rv = m_prefs->SavePrefFile(); if (NS_FAILED(rv)) return rv; @@ -1656,7 +1663,177 @@ nsMessengerMigrator::MigrateOldImapPrefs(nsIMsgIncomingServer *server, const cha return NS_OK; } + +static PRBool charEndsWith(const char *str, const char *endStr) +{ + PRUint32 endStrLen = PL_strlen(endStr); + PRUint32 strLen = PL_strlen(str); + + if (strLen < endStrLen) return PR_FALSE; + + PRUint32 pos = strLen - endStrLen; + if (PL_strncmp(str + pos, endStr, endStrLen) == 0) { + return PR_TRUE; + } + else { + return PR_FALSE; + } +} + +#define ADDRESSBOOK_PREF_NAME_ROOT "ldap_2.servers." +#define ADDRESSBOOK_PREF_NAME_SUFFIX ".filename" +#define ADDRESSBOOK_PREF_VALUE_4x_SUFFIX ".na2" +#define ADDRESSBOOK_PREF_VALUE_5x_SUFFIX ".mab" +#define TEMP_LDIF_FILE_SUFFIX ".ldif" + +#if defined(DEBUG_sspitzer) || defined(DEBUG_seth) +#define DEBUG_AB_MIGRATION 1 +#endif + +nsresult +nsMessengerMigrator::Convert4xAddressBookToLDIF(nsIFileSpec *srcFileSpec, nsIFileSpec *dstFileSpec) +{ + nsresult rv = NS_OK; + if (!srcFileSpec || !dstFileSpec) return NS_ERROR_NULL_POINTER; + nsCOMPtr abUpgrader = do_GetService(NS_AB4xUPGRADER_PROGID, &rv); + if (NS_FAILED(rv)) return rv; + if (!abUpgrader) return NS_ERROR_FAILURE; + + rv = abUpgrader->StartUpgrade4xAddrBook(srcFileSpec, dstFileSpec); + if (NS_SUCCEEDED(rv)) { + PRBool done = PR_FALSE; + + do { + rv = abUpgrader->ContinueExport(&done); + printf("grinding...\n"); + } while (NS_SUCCEEDED(rv) && !done); + } + return rv; +} + +void +nsMessengerMigrator::migrateAddressBookPrefEnum(const char *aPref, void *aClosure) +{ + nsresult rv = NS_OK; + nsIPref *prefs = (nsIPref *)aClosure; + +#ifdef DEBUG_AB_MIGRATION + printf("investigate pref: %s\n",aPref); +#endif + // we only care about ldap_2.servers.*.filename" prefs + if (!charEndsWith(aPref, ADDRESSBOOK_PREF_NAME_SUFFIX)) return; + + nsXPIDLCString abFileName; + rv = prefs->CopyCharPref(aPref,getter_Copies(abFileName)); + NS_ASSERTION(NS_SUCCEEDED(rv),"ab migration failed: failed to get ab filename"); + if (NS_FAILED(rv)) return; + + NS_ASSERTION(((const char *)abFileName), "ERROR: empty addressbook file name"); + if (!((const char *)abFileName)) return; + + NS_ASSERTION(PL_strlen((const char *)abFileName),"ERROR: empty addressbook file name"); + if (!(PL_strlen((const char *)abFileName))) return; + +#ifdef DEBUG_AB_MIGRATION + printf("pref value: %s\n",(const char *)abFileName); +#endif /* DEBUG_AB_MIGRATION */ + // if this a 5.x addressbook file name, skip it. + if (charEndsWith((const char *)abFileName, ADDRESSBOOK_PREF_VALUE_5x_SUFFIX)) return; + + nsCAutoString abName; + abName = (const char *)abFileName; + PRInt32 len = abName.Length(); + PRInt32 suffixLen = PL_strlen(ADDRESSBOOK_PREF_VALUE_4x_SUFFIX); + NS_ASSERTION(len > suffixLen, "ERROR: bad length of addressbook filename"); + if (len <= suffixLen) return; + + abName.SetLength(len - suffixLen); + + // get 5.0 profile root. + nsCOMPtr ab4xFile; + nsCOMPtr tmpLDIFFile; + +#ifdef DEBUG_AB_MIGRATION + printf("turn %s%s into %s%s\n", (const char *)abName,ADDRESSBOOK_PREF_VALUE_4x_SUFFIX,(const char *)abName,TEMP_LDIF_FILE_SUFFIX); +#endif /* DEBUG_AB_MIGRATION */ + + nsCOMPtr locator = do_GetService(kFileLocatorCID,&rv); + NS_ASSERTION(NS_SUCCEEDED(rv) && locator,"ab migration failed: failed to get locator"); + if (NS_FAILED(rv) || !locator) return; + + rv = locator->GetFileLocation(nsSpecialFileSpec::App_UserProfileDirectory50, getter_AddRefs(ab4xFile)); + NS_ASSERTION(NS_SUCCEEDED(rv) && ab4xFile,"ab migration failed: failed to get profile dir"); + if (NS_FAILED(rv) || !ab4xFile) return; + + rv = ab4xFile->AppendRelativeUnixPath((const char *)abFileName); + NS_ASSERTION(NS_SUCCEEDED(rv),"ab migration failed: failed to append filename"); + if (NS_FAILED(rv)) return; + + nsSpecialSystemDirectory file(nsSpecialSystemDirectory::OS_TemporaryDirectory); + rv = NS_NewFileSpecWithSpec(file, getter_AddRefs(tmpLDIFFile)); + NS_ASSERTION(NS_SUCCEEDED(rv) && tmpLDIFFile,"ab migration failed: failed to get tmp dir"); + if (NS_FAILED(rv) || !tmpLDIFFile) return; + + nsCAutoString ldifFileName; + ldifFileName = (const char *)abName; + ldifFileName += TEMP_LDIF_FILE_SUFFIX; + rv = tmpLDIFFile->AppendRelativeUnixPath((const char *)ldifFileName); + NS_ASSERTION(NS_SUCCEEDED(rv),"ab migration failed: failed to append filename"); + if (NS_FAILED(rv)) return; + + rv = Convert4xAddressBookToLDIF(ab4xFile, tmpLDIFFile); + NS_ASSERTION(NS_SUCCEEDED(rv),"ab migration failed: failed to convert to ldif"); + if (NS_FAILED(rv)) return; + +#ifdef DEBUG_AB_MIGRATION + printf("convert %s%s into %s%s\n",(const char *)abName,TEMP_LDIF_FILE_SUFFIX,(const char *)abName,ADDRESSBOOK_PREF_VALUE_5x_SUFFIX); +#endif /* DEBUG_AB_MIGRATION */ + + nsCOMPtr ab = do_CreateInstance(kAddressBookCID, &rv); + NS_ASSERTION(NS_SUCCEEDED(rv) && ab, "failed to get address book"); + if (NS_FAILED(rv) || !ab) return; + + rv = ab->ConvertLDIFtoMAB(tmpLDIFFile); + NS_ASSERTION(NS_SUCCEEDED(rv),"ab migration filed: ldif to mab conversion failed\n"); + if (NS_FAILED(rv)) return; + +#ifdef DEBUG_AB_MIGRATION + printf("set %s the pref to %s%s\n",aPref,(const char *)abName,ADDRESSBOOK_PREF_VALUE_5x_SUFFIX); +#endif /* DEBUG_AB_MIGRATION */ + + nsCAutoString newPrefValue; + newPrefValue = (const char *)abName; + newPrefValue += ADDRESSBOOK_PREF_VALUE_5x_SUFFIX; + rv = prefs->SetCharPref((const char *)aPref,(const char *)newPrefValue); + NS_ASSERTION(NS_SUCCEEDED(rv),"ab migration failed: failed to set pref"); + if (NS_FAILED(rv)) return; + +#ifdef DEBUG_AB_MIGRATION + printf("remove the tmp file\n"); +#endif /* DEBUG_AB_MIGRATION */ + rv = tmpLDIFFile->Delete(PR_TRUE); + NS_ASSERTION(NS_SUCCEEDED(rv),"failed to delete the temp ldif file"); + if (NS_FAILED(rv)) return; + + return; +} + +nsresult +nsMessengerMigrator::MigrateAddressBooks() +{ + nsresult rv = NS_OK; + + nsCOMPtr abUpgrader = do_GetService(NS_AB4xUPGRADER_PROGID, &rv); + if (NS_FAILED(rv) || !abUpgrader) { + printf("the addressbook migrator is only in the commercial builds.\n"); + return NS_OK; + } + + rv = m_prefs->EnumerateChildren(ADDRESSBOOK_PREF_NAME_ROOT, migrateAddressBookPrefEnum, (void *)m_prefs); + return rv; +} + #ifdef USE_NEWSRC_MAP_FILE #define NEWSRC_MAP_FILE_COOKIE "netscape-newsrc-map-file" #endif /* USE_NEWSRC_MAP_FILE */ diff --git a/mailnews/base/src/nsMessengerMigrator.h b/mailnews/base/src/nsMessengerMigrator.h index af41bcce8ae..dbb639ff504 100644 --- a/mailnews/base/src/nsMessengerMigrator.h +++ b/mailnews/base/src/nsMessengerMigrator.h @@ -113,6 +113,10 @@ private: nsresult MigrateNewsAccount(nsIMsgIdentity *identity, const char *hostAndPort, nsFileSpec &newsrcfile, nsFileSpec &newsHostsDir, PRBool isSecure); nsresult MigrateOldNntpPrefs(nsIMsgIncomingServer *server, const char *hostAndPort, nsFileSpec &newsrcfile); + nsresult MigrateAddressBooks(); + static void migrateAddressBookPrefEnum(const char *aPref, void *aClosure); + static nsresult Convert4xAddressBookToLDIF(nsIFileSpec *srcFileSpec, nsIFileSpec *dstFileSpec); + nsresult ProceedWithMigration(); nsresult Convert4XUri(const char *old_uri, PRBool for_news, const char *aUsername, const char *aHostname, const char *default_folder_name, char **new_uri);