Back to index

lightning-sunbird  0.9+nobinonly
nsMessengerMigrator.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Seth Spitzer <sspitzer@netscape.com>
00024  *   Alec Flett <alecf@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "nsIComponentManager.h"
00041 #include "nsIServiceManager.h"
00042 #include "nsISupportsArray.h"
00043 #include "nsSupportsPrimitives.h"
00044 #include "nsNetUtil.h"
00045 
00046 #include "prmem.h"
00047 #include "plstr.h"
00048 #include "prprf.h"
00049 #include "nsString.h"
00050 #include "nsXPIDLString.h"
00051 #include "nscore.h"
00052 
00053 #include "nsCRT.h"  // for nsCRT::strtok
00054 #include "nsFileStream.h"
00055 #include "nsIDirectoryService.h"
00056 #include "nsDirectoryServiceDefs.h"
00057 #include "nsAppDirectoryServiceDefs.h"
00058 #include "nsIFileSpec.h" 
00059 #include "nsILocalFile.h"
00060 #include "nsIURL.h"
00061 #include "nsNetCID.h"
00062 #include "nsIStringBundle.h"
00063 
00064 #include "nsMessengerMigrator.h"
00065 #include "nsMsgBaseCID.h"
00066 #include "nsMsgCompCID.h"
00067 
00068 #include "nsIMsgFolderCache.h"
00069 #include "nsMsgUtils.h"
00070 #include "nsISmtpService.h"
00071 #include "nsIObserverService.h"
00072 
00073 #include "nsIMsgAccount.h"
00074 #include "nsIMsgAccountManager.h"
00075 
00076 #include "nsIPop3IncomingServer.h"
00077 #include "nsIImapIncomingServer.h"
00078 #include "nsINntpIncomingServer.h"
00079 #include "nsINoIncomingServer.h"
00080 #include "nsIMsgProtocolInfo.h"
00081 #include "nsEscape.h"
00082 
00083 #include "nsIUserInfo.h"
00084 #include "nsIAbUpgrader.h"
00085 #include "nsIAddressBook.h"
00086 #include "nsAbBaseCID.h"
00087 
00088 #if defined(MOZ_LDAP_XPCOM)
00089 #include "nsILDAPPrefsService.h"
00090 #endif
00091 #include "nsIMsgFilterService.h"
00092 #include "nsIMsgFilterList.h"
00093 
00094 #define BUF_STR_LEN 1024
00095 
00096 #if defined(DEBUG_sspitzer) || defined(DEBUG_seth)
00097 #define DEBUG_MIGRATOR 1
00098 #endif
00099 
00100 #define IMAP_SCHEMA "imap:/"
00101 #define IMAP_SCHEMA_LENGTH 6
00102 #define MAILBOX_SCHEMA "mailbox:/"
00103 #define MAILBOX_SCHEMA_LENGTH 9
00104 
00105 #define POP_4X_MAIL_TYPE 0
00106 #define IMAP_4X_MAIL_TYPE 1
00107 #ifdef HAVE_MOVEMAIL
00108 #define MOVEMAIL_4X_MAIL_TYPE 2
00109 #endif /* HAVE_MOVEMAIL */
00110 
00111 /* TODO:  do we want to clear these after migration? */
00112 #define PREF_NEWS_DIRECTORY "news.directory"
00113 #define PREF_MAIL_DIRECTORY "mail.directory"
00114 #define PREF_PREMIGRATION_MAIL_DIRECTORY "premigration.mail.directory"
00115 #define PREF_PREMIGRATION_NEWS_DIRECTORY "premigration.news.directory"
00116 #define PREF_IMAP_DIRECTORY "mail.imap.root_dir"
00117 #define PREF_MAIL_DEFAULT_SENDLATER_URI "mail.default_sendlater_uri"
00118 
00119 #define LOCAL_MAIL_FAKE_USER_NAME "nobody"
00120 
00121 
00122 #ifdef HAVE_MOVEMAIL
00123 #define MOVEMAIL_FAKE_HOST_NAME "movemail"
00124 #endif /* HAVE_MOVEMAIL */
00125 #define DEFAULT_4X_DRAFTS_FOLDER_NAME "Drafts"
00126 #define DEFAULT_4X_SENT_FOLDER_NAME "Sent"
00127 #define DEFAULT_4X_TEMPLATES_FOLDER_NAME "Templates"
00128 #define UNSENT_MESSAGES_FOLDER_NAME "Unsent%20Messages"
00129 
00130 #define FILTER_FILE_NAME    "msgFilterRules.dat"        /* this is XP in 5.x */
00131 
00132 /* we are going to clear these after migration */
00133 #define PREF_4X_MAIL_IDENTITY_USEREMAIL "mail.identity.useremail"
00134 #define PREF_4X_MAIL_IDENTITY_USERNAME "mail.identity.username"
00135 #define PREF_4X_MAIL_IDENTITY_REPLY_TO "mail.identity.reply_to"    
00136 #define PREF_4X_MAIL_IDENTITY_ORGANIZATION "mail.identity.organization"
00137 #define PREF_4X_MAIL_SIGNATURE_FILE "mail.signature_file"
00138 #define PREF_4X_MAIL_SIGNATURE_DATE "mail.signature_date"
00139 #define PREF_4X_MAIL_COMPOSE_HTML "mail.html_compose"
00140 #define PREF_4X_MAIL_POP_NAME "mail.pop_name"
00141 #define PREF_4X_MAIL_REMEMBER_PASSWORD "mail.remember_password"
00142 #define PREF_4X_MAIL_POP_PASSWORD "mail.pop_password"
00143 #define PREF_4X_NETWORK_HOSTS_POP_SERVER "network.hosts.pop_server"
00144 #define PREF_4X_MAIL_CHECK_NEW_MAIL "mail.check_new_mail"
00145 #define PREF_4X_MAIL_POP3_GETS_NEW_MAIL   "mail.pop3_gets_new_mail"
00146 #define PREF_4X_MAIL_CHECK_TIME "mail.check_time"
00147 #define PREF_4X_MAIL_LEAVE_ON_SERVER "mail.leave_on_server"
00148 #define PREF_4X_MAIL_DELETE_MAIL_LEFT_ON_SERVER "mail.delete_mail_left_on_server"
00149 #define PREF_4X_NETWORK_HOSTS_SMTP_SERVER "network.hosts.smtp_server"
00150 #define PREF_4X_MAIL_SMTP_NAME "mail.smtp_name"
00151 #define PREF_4X_MAIL_SMTP_SSL "mail.smtp.ssl"
00152 #define PREF_4X_MAIL_SERVER_TYPE "mail.server_type"
00153 #define PREF_4X_NETWORK_HOSTS_IMAP_SERVER "network.hosts.imap_servers"
00154 #define PREF_4X_MAIL_USE_IMAP_SENTMAIL "mail.use_imap_sentmail"
00155 #define PREF_4X_NEWS_USE_IMAP_SENTMAIL "news.use_imap_sentmail"
00156 #define PREF_4X_MAIL_IMAP_SENTMAIL_PATH "mail.imap_sentmail_path"
00157 #define PREF_4X_NEWS_IMAP_SENTMAIL_PATH "news.imap_sentmail_path"
00158 #define PREF_4X_MAIL_DEFAULT_CC "mail.default_cc"
00159 #define PREF_4X_NEWS_DEFAULT_CC "news.default_cc"
00160 #define PREF_4X_MAIL_DEFAULT_FCC "mail.default_fcc"
00161 #define PREF_4X_NEWS_DEFAULT_FCC "news.default_fcc"
00162 #define PREF_4X_MAIL_USE_DEFAULT_CC "mail.use_default_cc"
00163 #define PREF_4X_NEWS_USE_DEFAULT_CC "news.use_default_cc"
00164 #define PREF_4X_MAIL_DEFAULT_DRAFTS "mail.default_drafts"
00165 #define PREF_4X_MAIL_DEFAULT_TEMPLATES "mail.default_templates"
00166 #define PREF_4X_MAIL_CC_SELF "mail.cc_self"
00167 #define PREF_4X_NEWS_CC_SELF "news.cc_self"
00168 #define PREF_4X_MAIL_USE_FCC "mail.use_fcc"
00169 #define PREF_4X_NEWS_USE_FCC "news.use_fcc"
00170 #define PREF_4X_NEWS_MAX_ARTICLES "news.max_articles"
00171 #define PREF_4X_NEWS_NOTIFY_ON "news.notify.on"
00172 #define PREF_4X_NEWS_MARK_OLD_READ "news.mark_old_read"
00173 #define PREF_4X_MAIL_ATTACH_VCARD "mail.attach_vcard"
00174 #define PREF_4X_MAIL_IDENTITY_VCARD_ROOT "mail.identity.vcard"
00175 
00176 #define PREF_4X_AUTOCOMPLETE_ON_LOCAL_AB "ldap_2.autoComplete.useAddressBooks"
00177 #define PREF_MOZILLA_AUTOCOMPLETE_ON_LOCAL_AB "mail.enable_autocomplete"
00178 
00179 #define DEFAULT_FCC_FOLDER_PREF_NAME "mail.identity.default.fcc_folder"
00180 #define DEFAULT_DRAFT_FOLDER_PREF_NAME  "mail.identity.default.draft_folder"
00181 #define DEFAULT_STATIONERY_FOLDER_PREF_NAME "mail.identity.default.stationery_folder"
00182 
00183 #define DEFAULT_PAB_FILENAME_PREF_NAME "ldap_2.servers.pab.filename"
00184 
00185 // this is for the hidden preference setting in mozilla/modules/libpref/src/init/mailnews.js
00186 // pref("mail.migration.copyMailFiles", true);
00187 //
00188 // see bugzilla bug 80035 (http://bugzilla.mozilla.org/show_bug.cgi?id=80035)
00189 //
00190 // the default value for this setting is true which means when migrating from
00191 // Netscape 4.x, mozilla will copy all the contents of Local Folders and Imap
00192 // Folder to the newly created subfolders of migrated mozilla profile
00193 // when this value is set to false, mozilla will not copy these contents and
00194 // still share them with Netscape 4.x
00195 //
00196 // Advantages of forbidding copy operation:
00197 //     reduce the disk usage
00198 //     quick migration
00199 // Disadvantage of forbidding copy operation:
00200 //     without perfect lock mechamism, there is possibility of data corruption
00201 //     when Netscape 4.x and mozilla run at the same time and access the same
00202 //     mail file at the same time
00203 #define PREF_MIGRATION_MODE_FOR_MAIL "mail.migration.copyMailFiles"
00204 
00205 #define ESCAPE_USER_NAME(outName,inName) \
00206     *((char **)getter_Copies(outName)) = nsEscape((const char *)inName, url_XAlphas);
00207 
00208 #define ESCAPE_FOLDER_NAME(outName,inName) \
00209     *((char **)getter_Copies(outName)) = nsEscape((const char *)inName, url_Path);
00210 
00211 
00212 #define CONVERT_4X_URI(IDENTITY,FOR_NEWS,USERNAME,HOSTNAME,DEFAULT_FOLDER_NAME,MACRO_GETTER,MACRO_SETTER,DEFAULT_PREF) \
00213 { \
00214   nsXPIDLCString macro_oldStr; \
00215   nsresult macro_rv; \
00216   macro_rv = IDENTITY->MACRO_GETTER(getter_Copies(macro_oldStr));     \
00217   if (NS_FAILED(macro_rv) || !macro_oldStr) { \
00218     IDENTITY->MACRO_SETTER("");    \
00219   }\
00220   else {      \
00221     char *converted_uri = nsnull; \
00222     macro_rv = Convert4XUri((const char *)macro_oldStr, FOR_NEWS, USERNAME, HOSTNAME, DEFAULT_FOLDER_NAME, DEFAULT_PREF, &converted_uri); \
00223     if (NS_FAILED(macro_rv)) { \
00224       IDENTITY->MACRO_SETTER("");  \
00225     } \
00226     else { \
00227       IDENTITY->MACRO_SETTER(converted_uri); \
00228     } \
00229     PR_FREEIF(converted_uri); \
00230   }    \
00231 }
00232 
00233 
00234 #define MIGRATE_SIMPLE_FILE_PREF_TO_BOOL_PREF(PREFNAME,MACRO_OBJECT,MACRO_METHOD) \
00235   { \
00236     nsresult macro_rv; \
00237     nsCOMPtr <nsIFileSpec>macro_spec;     \
00238     macro_rv = m_prefs->GetComplexValue(PREFNAME, NS_GET_IID(nsIFileSpec), getter_AddRefs(macro_spec)); \
00239     if (NS_SUCCEEDED(macro_rv)) { \
00240        char *macro_oldStr = nsnull; \
00241        macro_rv = macro_spec->GetUnixStyleFilePath(&macro_oldStr);    \
00242     if (NS_SUCCEEDED(macro_rv) && macro_oldStr && (PL_strlen(macro_oldStr))) { \
00243               MACRO_OBJECT->MACRO_METHOD(PR_TRUE); \
00244        }      \
00245        else { \
00246               MACRO_OBJECT->MACRO_METHOD(PR_FALSE); \
00247        }      \
00248        PR_FREEIF(macro_oldStr); \
00249     } \
00250   }
00251 
00252 
00253 #define MIGRATE_SIMPLE_FILE_PREF_TO_CHAR_PREF(PREFNAME,MACRO_OBJECT,MACRO_METHOD) \
00254   { \
00255     nsresult macro_rv; \
00256     nsCOMPtr <nsIFileSpec>macro_spec;     \
00257        char *macro_val = nsnull; \
00258        macro_rv = m_prefs->GetCharPref(PREFNAME, &macro_val); \
00259        if (NS_SUCCEEDED(macro_rv) && macro_val && PL_strlen(macro_val)) { \
00260               macro_rv = m_prefs->GetComplexValue(PREFNAME, NS_GET_IID(nsIFileSpec), getter_AddRefs(macro_spec)); \
00261               if (NS_SUCCEEDED(macro_rv)) { \
00262                      char *macro_oldStr = nsnull; \
00263                      macro_rv = macro_spec->GetUnixStyleFilePath(&macro_oldStr);    \
00264               if (NS_SUCCEEDED(macro_rv)) { \
00265                             MACRO_OBJECT->MACRO_METHOD(macro_oldStr); \
00266             } \
00267             PR_FREEIF(macro_oldStr); \
00268        } \
00269        } \
00270        else { \
00271               MACRO_OBJECT->MACRO_METHOD(""); \
00272        }      \
00273     PR_FREEIF(macro_val); \
00274   }
00275 
00276 #define MIGRATE_SIMPLE_FILE_PREF_TO_FILE_PREF(PREFNAME,MACRO_OBJECT,MACRO_METHOD) \
00277   { \
00278     nsresult macro_rv; \
00279     nsCOMPtr <nsILocalFile> macro_file; \
00280     char *macro_oldStr = nsnull; \
00281     macro_rv = m_prefs->GetCharPref(PREFNAME, &macro_oldStr); \
00282     if (NS_SUCCEEDED(macro_rv) && macro_oldStr && PL_strlen(macro_oldStr)) { \
00283       macro_rv = m_prefs->GetComplexValue(PREFNAME, NS_GET_IID(nsILocalFile), getter_AddRefs(macro_file)); \
00284       if (NS_SUCCEEDED(macro_rv)) { \
00285         MACRO_OBJECT->MACRO_METHOD(macro_file); \
00286       } \
00287     } \
00288     PR_FREEIF(macro_oldStr); \
00289   }
00290 
00291 #define MIGRATE_SIMPLE_STR_PREF(PREFNAME,MACRO_OBJECT,MACRO_METHOD) \
00292   { \
00293     nsresult macro_rv; \
00294     char *macro_oldStr = nsnull; \
00295     macro_rv = m_prefs->GetCharPref(PREFNAME, &macro_oldStr); \
00296     if (NS_SUCCEEDED(macro_rv)) { \
00297       MACRO_OBJECT->MACRO_METHOD(macro_oldStr); \
00298     } \
00299     PR_FREEIF(macro_oldStr); \
00300   }
00301 
00302 #define MIGRATE_SIMPLE_WSTR_PREF(PREFNAME,MACRO_OBJECT,MACRO_METHOD) \
00303   { \
00304     nsresult macro_rv; \
00305     PRUnichar *macro_oldStr = nsnull; \
00306     nsCOMPtr<nsISupportsString> macro_tmpstr; \
00307     macro_rv = m_prefs->GetComplexValue(PREFNAME, NS_GET_IID(nsISupportsString), getter_AddRefs(macro_tmpstr)); \
00308     if (NS_SUCCEEDED(macro_rv)) { \
00309       macro_tmpstr->ToString(&macro_oldStr); \
00310       MACRO_OBJECT->MACRO_METHOD(macro_oldStr); \
00311     } \
00312     PR_FREEIF(macro_oldStr); \
00313   }
00314 
00315 #define MIGRATE_SIMPLE_INT_PREF(PREFNAME,MACRO_OBJECT,MACRO_METHOD) \
00316   { \
00317     nsresult macro_rv; \
00318     PRInt32 oldInt; \
00319     macro_rv = m_prefs->GetIntPref(PREFNAME, &oldInt); \
00320     if (NS_SUCCEEDED(macro_rv)) { \
00321       MACRO_OBJECT->MACRO_METHOD(oldInt); \
00322     } \
00323   }
00324 
00325 #define MIGRATE_SIMPLE_BOOL_PREF(PREFNAME,MACRO_OBJECT,MACRO_METHOD) \
00326   { \
00327     nsresult macro_rv; \
00328     PRBool macro_oldBool; \
00329     macro_rv = m_prefs->GetBoolPref(PREFNAME, &macro_oldBool); \
00330     if (NS_SUCCEEDED(macro_rv)) { \
00331       MACRO_OBJECT->MACRO_METHOD(macro_oldBool); \
00332     } \
00333   }
00334 
00335 #define MIGRATE_STR_PREF(PREFFORMATSTR,PREFFORMATVALUE,INCOMINGSERVERPTR,INCOMINGSERVERMETHOD) \
00336   { \
00337     nsresult macro_rv; \
00338     char prefName[BUF_STR_LEN]; \
00339     char *macro_oldStr = nsnull; \
00340     PR_snprintf(prefName, BUF_STR_LEN, PREFFORMATSTR, PREFFORMATVALUE); \
00341     macro_rv = m_prefs->GetCharPref(prefName, &macro_oldStr); \
00342     if (NS_SUCCEEDED(macro_rv)) { \
00343       INCOMINGSERVERPTR->INCOMINGSERVERMETHOD(macro_oldStr); \
00344     } \
00345     PR_FREEIF(macro_oldStr); \
00346   }
00347 
00348 #define MIGRATE_INT_PREF(PREFFORMATSTR,PREFFORMATVALUE,INCOMINGSERVERPTR,INCOMINGSERVERMETHOD) \
00349   { \
00350     nsresult macro_rv; \
00351     PRInt32 oldInt; \
00352     char prefName[BUF_STR_LEN]; \
00353     PR_snprintf(prefName, BUF_STR_LEN, PREFFORMATSTR, PREFFORMATVALUE); \
00354     macro_rv = m_prefs->GetIntPref(prefName, &oldInt); \
00355     if (NS_SUCCEEDED(macro_rv)) { \
00356       INCOMINGSERVERPTR->INCOMINGSERVERMETHOD(oldInt); \
00357     } \
00358   }
00359 
00360 #define MIGRATE_BOOL_PREF(PREFFORMATSTR,PREFFORMATVALUE,INCOMINGSERVERPTR,INCOMINGSERVERMETHOD) \
00361   { \
00362     nsresult macro_rv; \
00363     PRBool macro_oldBool; \
00364     char prefName[BUF_STR_LEN]; \
00365     PR_snprintf(prefName, BUF_STR_LEN, PREFFORMATSTR, PREFFORMATVALUE); \
00366     macro_rv = m_prefs->GetBoolPref(prefName, &macro_oldBool); \
00367     if (NS_SUCCEEDED(macro_rv)) { \
00368       INCOMINGSERVERPTR->INCOMINGSERVERMETHOD(macro_oldBool); \
00369     } \
00370   }
00371 
00372 NS_IMPL_ISUPPORTS2(nsMessengerMigrator, nsIMessengerMigrator, nsIObserver)
00373 
00374 nsMessengerMigrator::nsMessengerMigrator() :
00375   m_haveShutdown(PR_FALSE)
00376 {
00377 }
00378 
00379 nsMessengerMigrator::~nsMessengerMigrator()
00380 {
00381   nsresult rv;
00382 
00383   if(!m_haveShutdown)
00384   {
00385     Shutdown();
00386     //Don't remove from Observer service in Shutdown because Shutdown also gets called
00387     //from xpcom shutdown observer.  And we don't want to remove from the service in that case.
00388     nsCOMPtr<nsIObserverService> observerService = 
00389              do_GetService("@mozilla.org/observer-service;1", &rv);
00390     if (NS_SUCCEEDED(rv))
00391     {
00392       observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
00393     }
00394   }     
00395 }
00396 
00397 nsresult nsMessengerMigrator::Init()
00398 {
00399   nsresult rv;
00400 
00401   nsCOMPtr<nsIObserverService> observerService = 
00402            do_GetService("@mozilla.org/observer-service;1", &rv);
00403   if (NS_SUCCEEDED(rv))
00404   {
00405     observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
00406   }    
00407 
00408   initializeStrings();
00409   
00410   rv = getPrefService();
00411   if (NS_FAILED(rv)) return rv;   
00412 
00413   rv = ResetState();
00414   return rv;
00415 }
00416 
00417 nsresult 
00418 nsMessengerMigrator::Shutdown()
00419 {
00420   m_prefs = nsnull;
00421 
00422   m_haveShutdown = PR_TRUE;
00423   return NS_OK;
00424 }       
00425 
00426 nsresult
00427 nsMessengerMigrator::getPrefService()
00428 {
00429   nsresult rv = NS_OK;
00430 
00431   if (!m_prefs) {
00432     m_prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
00433   }
00434 
00435   if (NS_FAILED(rv)) return rv;
00436 
00437   if (!m_prefs) return NS_ERROR_FAILURE;
00438 
00439   return NS_OK;
00440 } 
00441 
00442 nsresult
00443 nsMessengerMigrator::initializeStrings()
00444 {
00445   nsresult rv;
00446   nsCOMPtr<nsIStringBundleService> bundleService =
00447     do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
00448   NS_ENSURE_SUCCESS(rv, rv);
00449   
00450   nsCOMPtr<nsIStringBundle> bundle;
00451   rv = bundleService->CreateBundle("chrome://messenger/locale/messenger.properties",
00452                                    getter_AddRefs(bundle));
00453   NS_ENSURE_SUCCESS(rv, rv);
00454   
00455   // now retrieve strings
00456   nsXPIDLString localFolders;
00457   rv = bundle->GetStringFromName(NS_LITERAL_STRING("localFolders").get(),
00458                                  getter_Copies(localFolders));
00459   NS_ENSURE_SUCCESS(rv, rv);
00460   // convert to unicode and ASCII
00461 
00462   mLocalFoldersName.Assign(localFolders);
00463   mLocalFoldersHostname = "Local Folders";
00464 
00465   return NS_OK;
00466 }
00467 
00468 
00469 
00470 NS_IMETHODIMP nsMessengerMigrator::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
00471 {
00472   if(!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID))
00473   {
00474     Shutdown();
00475   }
00476 
00477   return NS_OK;
00478 }           
00479 
00480 nsresult
00481 nsMessengerMigrator::ProceedWithMigration()
00482 {
00483   char *prefvalue = nsnull;
00484   nsresult rv = NS_OK;
00485   
00486   if ((m_oldMailType == POP_4X_MAIL_TYPE) 
00487 #ifdef HAVE_MOVEMAIL
00488        || (m_oldMailType == MOVEMAIL_4X_MAIL_TYPE) 
00489 #endif /* HAVE_MOVEMAIL */
00490        ) {
00491     // if they were using pop or movemail, "mail.pop_name" must have been set
00492     // otherwise, they don't really have anything to migrate
00493     rv = m_prefs->GetCharPref(PREF_4X_MAIL_POP_NAME, &prefvalue);
00494     if (NS_SUCCEEDED(rv)) {
00495            if (!prefvalue || !*prefvalue) {
00496              rv = NS_ERROR_FAILURE;
00497            }
00498     }
00499   }
00500   else if (m_oldMailType == IMAP_4X_MAIL_TYPE) {
00501     // if they were using imap, "network.hosts.imap_servers" must have been set
00502     // otherwise, they don't really have anything to migrate
00503     rv = m_prefs->GetCharPref(PREF_4X_NETWORK_HOSTS_IMAP_SERVER, &prefvalue);
00504     if (NS_SUCCEEDED(rv)) {
00505            if (!prefvalue || !*prefvalue) {
00506              rv = NS_ERROR_FAILURE;
00507            }
00508     }
00509   }
00510   else {
00511 #ifdef DEBUG_MIGRATOR
00512     printf("Unrecognized server type %d\n", m_oldMailType);
00513 #endif
00514     rv = NS_ERROR_UNEXPECTED;
00515   }
00516 
00517   PR_FREEIF(prefvalue);
00518   return rv;
00519 }
00520 
00521 NS_IMETHODIMP
00522 nsMessengerMigrator::CreateLocalMailAccount(PRBool migrating)
00523 {
00524   nsresult rv;
00525   nsCOMPtr<nsIMsgAccountManager> accountManager = 
00526            do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
00527   if (NS_FAILED(rv)) return rv;
00528 
00529   // create the server
00530   nsCOMPtr<nsIMsgIncomingServer> server;
00531   rv = accountManager->CreateIncomingServer(LOCAL_MAIL_FAKE_USER_NAME,
00532                                             mLocalFoldersHostname.get(),
00533                             "none", getter_AddRefs(server));
00534   NS_ENSURE_SUCCESS(rv,rv);
00535 
00536   // we don't want "nobody at Local Folders" to show up in the
00537   // folder pane, so we set the pretty name to "Local Folders"
00538   server->SetPrettyName(mLocalFoldersName.get());
00539 
00540   nsCOMPtr<nsINoIncomingServer> noServer;
00541   noServer = do_QueryInterface(server, &rv);
00542   if (NS_FAILED(rv)) return rv;
00543    
00544   // create the directory structure for old 4.x "Local Mail"
00545   // under <profile dir>/Mail/Local Folders or
00546   // <"mail.directory" pref>/Local Folders 
00547   nsCOMPtr <nsIFile> mailDir;
00548   nsFileSpec dir;
00549   PRBool dirExists;
00550 
00551   // if the "mail.directory" pref is set, use that.
00552   // if they used -installer, this pref will point to where their files got copied
00553   // this only makes sense when we are migrating
00554   // for a new profile, that pref won't be set.
00555   if (migrating) {
00556     nsCOMPtr<nsILocalFile> localFile;
00557     rv = m_prefs->GetComplexValue(PREF_MAIL_DIRECTORY, NS_GET_IID(nsILocalFile), getter_AddRefs(localFile));
00558     if (NS_SUCCEEDED(rv))
00559         mailDir = localFile;
00560   }
00561 
00562   if (!mailDir) {
00563     // we want <profile>/Mail
00564     rv = NS_GetSpecialDirectory(NS_APP_MAIL_50_DIR, getter_AddRefs(mailDir));
00565     if (NS_FAILED(rv)) return rv;
00566   }
00567   
00568   rv = mailDir->Exists(&dirExists);
00569   if (NS_SUCCEEDED(rv) && !dirExists)
00570     rv = mailDir->Create(nsIFile::DIRECTORY_TYPE, 0775);
00571   if (NS_FAILED(rv)) return rv; 
00572    
00573   nsXPIDLCString descString;
00574   nsCOMPtr<nsIFileSpec> mailDirSpec;
00575   
00576   // Convert the nsILocalFile into an nsIFileSpec
00577   // TODO: convert users os nsIFileSpec to nsILocalFile
00578   // and avoid this step.
00579   rv = NS_NewFileSpecFromIFile(mailDir, getter_AddRefs(mailDirSpec));
00580   if (NS_FAILED(rv)) return rv;
00581 
00582   // set the default local path for "none"
00583   rv = server->SetDefaultLocalPath(mailDirSpec);
00584   if (NS_FAILED(rv)) return rv;
00585  
00586   if (migrating) {
00587        // set the local path for this "none" server
00588        //
00589        // we need to set this to <profile>/Mail/Local Folders, because that's where
00590        // the 4.x "Local Mail" (when using imap) got copied.
00591        // it would be great to use the server key, but we don't know it
00592        // when we are copying of the mail.
00593        rv = mailDirSpec->AppendRelativeUnixPath(mLocalFoldersHostname.get());
00594        if (NS_FAILED(rv)) return rv; 
00595        rv = server->SetLocalPath(mailDirSpec);
00596        if (NS_FAILED(rv)) return rv;
00597     
00598        rv = mailDirSpec->Exists(&dirExists);
00599        if (!dirExists) {
00600            mailDirSpec->CreateDir();
00601        }
00602   }
00603 
00604   // Create an account when valid server values are established.
00605   // This will keep the status of accounts sane by avoiding the addition of incomplete accounts. 
00606   nsCOMPtr<nsIMsgAccount> account;
00607   rv = accountManager->CreateAccount(getter_AddRefs(account));
00608   if (NS_FAILED(rv)) return rv;
00609 
00610   // notice, no identity for local mail
00611   // hook the server to the account 
00612   // after we set the server's local path
00613   // (see bug #66018)
00614   account->SetIncomingServer(server);
00615 
00616   // remember this as the local folders server
00617   rv = accountManager->SetLocalFoldersServer(server);
00618   if (NS_FAILED(rv)) return rv;
00619 
00620   return NS_OK;
00621 }
00622 
00623 nsresult
00624 nsMessengerMigrator::ResetState()
00625 {
00626   m_alreadySetNntpDefaultLocalPath = PR_FALSE;
00627   m_alreadySetImapDefaultLocalPath = PR_FALSE;
00628 
00629   // Reset 'm_oldMailType' in case the prefs file has changed. This is possible in quick launch
00630   // mode where the profile to be migrated is IMAP type but the current working profile is POP.
00631   nsresult rv = m_prefs->GetIntPref(PREF_4X_MAIL_SERVER_TYPE, &m_oldMailType);
00632   if (NS_FAILED(rv))
00633     m_oldMailType = -1;
00634   return rv;
00635 }
00636 
00637 NS_IMETHODIMP
00638 nsMessengerMigrator::UpgradePrefs()
00639 {
00640     nsresult rv;
00641 
00642     rv = getPrefService();
00643     if (NS_FAILED(rv)) return rv;
00644 
00645     // Reset some control vars, necessary in turbo mode.
00646     ResetState();
00647 
00648     // because mail.server_type defaults to 0 (pop) it will look the user
00649     // has something to migrate, even with an empty prefs.js file
00650     // ProceedWithMigration will check if there is something to migrate
00651     // if not, NS_FAILED(rv) will be true, and we'll return.
00652     // this plays nicely with msgMail3PaneWindow.js, which will launch the
00653     // Account Wizard if UpgradePrefs() fails.
00654     rv = ProceedWithMigration();
00655     if (NS_FAILED(rv)) {
00656 #ifdef DEBUG_MIGRATOR
00657       printf("FAIL:  don't proceed with migration.\n");
00658 #endif
00659       return rv;
00660     }
00661 #ifdef DEBUG_MIGRATOR
00662     else {
00663       printf("PASS:  proceed with migration.\n");
00664     }
00665 #endif 
00666 
00667     nsCOMPtr<nsIMsgAccountManager> accountManager = 
00668              do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
00669     if (NS_FAILED(rv)) return rv;
00670 
00671     // create a dummy identity, for migration only
00672     nsCOMPtr<nsIMsgIdentity> identity;
00673 
00674     rv = accountManager->CreateIdentity(getter_AddRefs(identity));
00675     if (NS_FAILED(rv)) return rv;
00676 
00677     rv = MigrateIdentity(identity);
00678     if (NS_FAILED(rv)) return rv;    
00679     
00680     nsCOMPtr<nsISmtpService> smtpService = 
00681              do_GetService(NS_SMTPSERVICE_CONTRACTID, &rv);
00682     if (NS_FAILED(rv)) return rv;    
00683 
00684     nsCOMPtr<nsISmtpServer> smtpServer;
00685     rv = smtpService->CreateSmtpServer(getter_AddRefs(smtpServer));
00686     if (NS_FAILED(rv)) return rv;    
00687 
00688     rv = MigrateSmtpServer(smtpServer);
00689     if (NS_FAILED(rv)) return rv;    
00690 
00691     // set the newly created smtp server as the default
00692     smtpService->SetDefaultServer(smtpServer); // ignore the error code....continue even if this call fails...
00693 
00694 
00695     if ( m_oldMailType == POP_4X_MAIL_TYPE) {
00696       // in 4.x, you could only have one pop account
00697       rv = MigratePopAccount(identity);
00698       if (NS_FAILED(rv)) return rv;
00699 
00700       // everyone gets a local mail account in 5.0
00701       rv = CreateLocalMailAccount(PR_TRUE);
00702       if (NS_FAILED(rv)) return rv;
00703     }
00704     else if (m_oldMailType == IMAP_4X_MAIL_TYPE) {
00705       rv = MigrateImapAccounts(identity);
00706       if (NS_FAILED(rv)) return rv;
00707       
00708       // if they had IMAP in 4.x, they also had "Local Mail"
00709       // we'll migrate that to "Local Folders"
00710       rv = MigrateLocalMailAccount();
00711       if (NS_FAILED(rv)) return rv;
00712     }
00713 #ifdef HAVE_MOVEMAIL
00714     else if (m_oldMailType == MOVEMAIL_4X_MAIL_TYPE) {
00715        // if 4.x, you could only have one movemail account
00716        rv = MigrateMovemailAccount(identity);
00717        if (NS_FAILED(rv)) return rv;
00718 
00719         // everyone gets a local mail account in 5.0
00720         rv = CreateLocalMailAccount(PR_TRUE);
00721         if (NS_FAILED(rv)) return rv;
00722     }
00723 #endif /* HAVE_MOVEMAIL */
00724     else {
00725 #ifdef DEBUG_MIGRATOR
00726       printf("Unrecognized server type %d\n", m_oldMailType);
00727 #endif
00728       return NS_ERROR_UNEXPECTED;
00729     }
00730 
00731     rv = MigrateNewsAccounts(identity);
00732     if (NS_FAILED(rv)) return rv;
00733 
00734     // this will upgrade the ldap prefs
00735 #if defined(MOZ_LDAP_XPCOM)
00736     nsCOMPtr <nsILDAPPrefsService> ldapPrefsService = do_GetService("@mozilla.org/ldapprefs-service;1", &rv);
00737 #endif    
00738     rv = MigrateAddressBookPrefs();
00739     NS_ENSURE_SUCCESS(rv,rv);
00740 
00741     rv = MigrateAddressBooks();
00742     if (NS_FAILED(rv)) return rv;
00743 
00744     m_prefs->ClearUserPref(PREF_4X_MAIL_POP_PASSWORD); // intentionally ignore the return value
00745 
00746     // we're done migrating, let's save the prefs
00747     nsCOMPtr<nsIPrefService> prefService(do_QueryInterface(m_prefs, &rv));
00748     if (NS_FAILED(rv)) return rv;
00749 
00750     rv = prefService->SavePrefFile(nsnull);
00751     if (NS_FAILED(rv)) return rv;
00752 
00753        // remove the temporary identity we used for migration purposes
00754     identity->ClearAllValues();
00755     rv = accountManager->RemoveIdentity(identity);
00756 
00757     return rv;
00758 }
00759 
00760 nsresult 
00761 nsMessengerMigrator::SetUsernameIfNecessary()
00762 {
00763     nsresult rv;
00764     nsXPIDLCString usernameIn4x;
00765 
00766     rv = m_prefs->GetCharPref(PREF_4X_MAIL_IDENTITY_USERNAME, getter_Copies(usernameIn4x));
00767     if (NS_SUCCEEDED(rv) && !usernameIn4x.IsEmpty()) {
00768         return NS_OK;
00769     }
00770 
00771     nsXPIDLString fullnameFromSystem;
00772     
00773     nsCOMPtr<nsIUserInfo> userInfo = do_GetService(NS_USERINFO_CONTRACTID, &rv);
00774     if (NS_FAILED(rv)) return rv;
00775 
00776     if (!userInfo) return NS_ERROR_FAILURE;
00777 
00778     rv = userInfo->GetFullname(getter_Copies(fullnameFromSystem));
00779     if (NS_FAILED(rv) || !((const PRUnichar *)fullnameFromSystem)) {
00780         // it is ok not to have this from the system
00781         return NS_OK;
00782     }
00783 
00784     nsCOMPtr<nsISupportsString> str(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv));
00785     if (NS_SUCCEEDED(rv)) {
00786         str->SetData(fullnameFromSystem);
00787         rv = m_prefs->SetComplexValue(PREF_4X_MAIL_IDENTITY_USERNAME, NS_GET_IID(nsISupportsString), str);
00788     }
00789 
00790     return rv;
00791 }
00792 
00793 nsresult
00794 nsMessengerMigrator::MigrateIdentity(nsIMsgIdentity *identity)
00795 {
00796   nsresult rv;
00797   
00798   rv = SetUsernameIfNecessary();
00799   /* SetUsernameIfNecessary() can fail. */
00800   //if (NS_FAILED(rv)) return rv;
00801 
00802   /* NOTE:  if you add prefs here, make sure you update nsMsgIdentity::Copy() */
00803   MIGRATE_SIMPLE_STR_PREF(PREF_4X_MAIL_IDENTITY_USEREMAIL,identity,SetEmail)
00804   MIGRATE_SIMPLE_WSTR_PREF(PREF_4X_MAIL_IDENTITY_USERNAME,identity,SetFullName)
00805   MIGRATE_SIMPLE_STR_PREF(PREF_4X_MAIL_IDENTITY_REPLY_TO,identity,SetReplyTo)
00806   MIGRATE_SIMPLE_WSTR_PREF(PREF_4X_MAIL_IDENTITY_ORGANIZATION,identity,SetOrganization)
00807   MIGRATE_SIMPLE_BOOL_PREF(PREF_4X_MAIL_COMPOSE_HTML,identity,SetComposeHtml)
00808   MIGRATE_SIMPLE_FILE_PREF_TO_FILE_PREF(PREF_4X_MAIL_SIGNATURE_FILE,identity,SetSignature)
00809   MIGRATE_SIMPLE_FILE_PREF_TO_BOOL_PREF(PREF_4X_MAIL_SIGNATURE_FILE,identity,SetAttachSignature)
00810   MIGRATE_SIMPLE_INT_PREF(PREF_4X_MAIL_SIGNATURE_DATE,identity,SetSignatureDate)
00811 
00812   MIGRATE_SIMPLE_BOOL_PREF(PREF_4X_MAIL_ATTACH_VCARD, identity, SetAttachVCard)
00813   nsCOMPtr <nsIAddressBook> ab = do_CreateInstance(NS_ADDRESSBOOK_CONTRACTID);
00814   if (ab) 
00815   {
00816       nsXPIDLCString escapedVCardStr;
00817       rv = ab->Convert4xVCardPrefs(PREF_4X_MAIL_IDENTITY_VCARD_ROOT, getter_Copies(escapedVCardStr));
00818       if (NS_SUCCEEDED(rv) && !escapedVCardStr.IsEmpty()) 
00819       {
00820           rv = identity->SetEscapedVCard(escapedVCardStr.get());
00821           NS_ASSERTION(NS_SUCCEEDED(rv), "failed to set escaped vCard string");
00822       }
00823   }    
00824 
00825   /* NOTE:  if you add prefs here, make sure you update nsMsgIdentity::Copy() */
00826   return NS_OK;
00827 }
00828 
00829 nsresult
00830 nsMessengerMigrator::MigrateSmtpServer(nsISmtpServer *server)
00831 {
00832   MIGRATE_SIMPLE_STR_PREF(PREF_4X_NETWORK_HOSTS_SMTP_SERVER,server,SetHostname)
00833   MIGRATE_SIMPLE_STR_PREF(PREF_4X_MAIL_SMTP_NAME,server,SetUsername)
00834   MIGRATE_SIMPLE_INT_PREF(PREF_4X_MAIL_SMTP_SSL,server,SetTrySSL)
00835 
00836   return NS_OK;
00837 }
00838 
00839 nsresult
00840 nsMessengerMigrator::SetNewsCopiesAndFolders(nsIMsgIdentity *identity)
00841 {
00842   nsresult rv;
00843   
00844   MIGRATE_SIMPLE_BOOL_PREF(PREF_4X_NEWS_CC_SELF,identity,SetBccSelf)
00845   MIGRATE_SIMPLE_BOOL_PREF(PREF_4X_NEWS_USE_DEFAULT_CC,identity,SetBccOthers)
00846   MIGRATE_SIMPLE_STR_PREF(PREF_4X_NEWS_DEFAULT_CC,identity,SetBccList)
00847   MIGRATE_SIMPLE_BOOL_PREF(PREF_4X_NEWS_USE_FCC,identity,SetDoFcc)
00848   MIGRATE_SIMPLE_STR_PREF(PREF_4X_MAIL_DEFAULT_DRAFTS,identity,SetDraftFolder)
00849   MIGRATE_SIMPLE_STR_PREF(PREF_4X_MAIL_DEFAULT_TEMPLATES,identity,SetStationeryFolder)
00850       
00851   PRBool news_used_uri_for_sent_in_4x;
00852   rv = m_prefs->GetBoolPref(PREF_4X_NEWS_USE_IMAP_SENTMAIL, &news_used_uri_for_sent_in_4x);
00853   if (NS_FAILED(rv)) {
00854          MIGRATE_SIMPLE_FILE_PREF_TO_CHAR_PREF(PREF_4X_NEWS_DEFAULT_FCC,identity,SetFccFolder)
00855   }
00856   else {
00857          if (news_used_uri_for_sent_in_4x) {
00858            MIGRATE_SIMPLE_STR_PREF(PREF_4X_NEWS_IMAP_SENTMAIL_PATH,identity,SetFccFolder)
00859          }
00860          else {
00861            MIGRATE_SIMPLE_FILE_PREF_TO_CHAR_PREF(PREF_4X_NEWS_DEFAULT_FCC,identity,SetFccFolder)
00862          }
00863   }
00864 
00865   if (m_oldMailType == IMAP_4X_MAIL_TYPE) {
00866        CONVERT_4X_URI(identity, PR_TRUE /* for news */, LOCAL_MAIL_FAKE_USER_NAME, mLocalFoldersHostname.get(), DEFAULT_4X_SENT_FOLDER_NAME,GetFccFolder,SetFccFolder,DEFAULT_FCC_FOLDER_PREF_NAME)
00867        CONVERT_4X_URI(identity, PR_TRUE /* for news */, LOCAL_MAIL_FAKE_USER_NAME, mLocalFoldersHostname.get(), DEFAULT_4X_TEMPLATES_FOLDER_NAME,GetStationeryFolder,SetStationeryFolder,DEFAULT_STATIONERY_FOLDER_PREF_NAME)
00868        CONVERT_4X_URI(identity, PR_TRUE /* for news */, LOCAL_MAIL_FAKE_USER_NAME, mLocalFoldersHostname.get(), DEFAULT_4X_DRAFTS_FOLDER_NAME,GetDraftFolder,SetDraftFolder,DEFAULT_DRAFT_FOLDER_PREF_NAME)
00869   }
00870   else if (m_oldMailType == POP_4X_MAIL_TYPE) {
00871     nsXPIDLCString pop_username;
00872     nsXPIDLCString pop_hostname;
00873 
00874     rv = m_prefs->GetCharPref(PREF_4X_MAIL_POP_NAME,getter_Copies(pop_username));
00875     if (NS_FAILED(rv)) return rv;
00876 
00877     rv = m_prefs->GetCharPref(PREF_4X_NETWORK_HOSTS_POP_SERVER, getter_Copies(pop_hostname));
00878     if (NS_FAILED(rv)) return rv;
00879 
00880        CONVERT_4X_URI(identity, PR_TRUE /* for news */, pop_username.get(), pop_hostname.get(), DEFAULT_4X_SENT_FOLDER_NAME,GetFccFolder,SetFccFolder,DEFAULT_FCC_FOLDER_PREF_NAME)
00881        CONVERT_4X_URI(identity, PR_TRUE /* for news */, pop_username.get(), pop_hostname.get(), DEFAULT_4X_TEMPLATES_FOLDER_NAME,GetStationeryFolder,SetStationeryFolder,DEFAULT_STATIONERY_FOLDER_PREF_NAME)
00882        CONVERT_4X_URI(identity, PR_TRUE /* for news */, pop_username.get(), pop_hostname.get(), DEFAULT_4X_DRAFTS_FOLDER_NAME,GetDraftFolder,SetDraftFolder,DEFAULT_DRAFT_FOLDER_PREF_NAME)
00883   }
00884 #ifdef HAVE_MOVEMAIL
00885   else if (m_oldMailType == MOVEMAIL_4X_MAIL_TYPE) {
00886     nsXPIDLCString pop_username;
00887 
00888        rv = m_prefs->GetCharPref(PREF_4X_MAIL_POP_NAME, getter_Copies(pop_username));
00889     if (NS_FAILED(rv)) return rv;
00890 
00891        CONVERT_4X_URI(identity, PR_TRUE /* for news */, pop_username.get(), MOVEMAIL_FAKE_HOST_NAME, DEFAULT_4X_SENT_FOLDER_NAME,GetFccFolder,SetFccFolder,DEFAULT_FCC_FOLDER_PREF_NAME)
00892        CONVERT_4X_URI(identity, PR_TRUE /* for news */, pop_username.get(), MOVEMAIL_FAKE_HOST_NAME, DEFAULT_4X_TEMPLATES_FOLDER_NAME,GetStationeryFolder,SetStationeryFolder,DEFAULT_STATIONERY_FOLDER_PREF_NAME)
00893        CONVERT_4X_URI(identity, PR_TRUE /* for news */, pop_username.get(), MOVEMAIL_FAKE_HOST_NAME, DEFAULT_4X_DRAFTS_FOLDER_NAME,GetDraftFolder,SetDraftFolder,DEFAULT_DRAFT_FOLDER_PREF_NAME)
00894   }
00895 #endif /* HAVE_MOVEMAIL */
00896   else {
00897        return NS_ERROR_UNEXPECTED;
00898   }
00899 
00900   return NS_OK;
00901 }
00902 
00903 nsresult
00904 nsMessengerMigrator::SetMailCopiesAndFolders(nsIMsgIdentity *identity, const char *username, const char *hostname)
00905 {
00906   nsresult rv;
00907   
00908   MIGRATE_SIMPLE_BOOL_PREF(PREF_4X_MAIL_CC_SELF,identity,SetBccSelf)
00909   MIGRATE_SIMPLE_BOOL_PREF(PREF_4X_MAIL_USE_DEFAULT_CC,identity,SetBccOthers)
00910   MIGRATE_SIMPLE_STR_PREF(PREF_4X_MAIL_DEFAULT_CC,identity,SetBccList)
00911   MIGRATE_SIMPLE_BOOL_PREF(PREF_4X_MAIL_USE_FCC,identity,SetDoFcc)
00912   MIGRATE_SIMPLE_STR_PREF(PREF_4X_MAIL_DEFAULT_DRAFTS,identity,SetDraftFolder)
00913   MIGRATE_SIMPLE_STR_PREF(PREF_4X_MAIL_DEFAULT_TEMPLATES,identity,SetStationeryFolder)
00914 
00915   PRBool imap_used_uri_for_sent_in_4x;
00916   rv = m_prefs->GetBoolPref(PREF_4X_MAIL_USE_IMAP_SENTMAIL, &imap_used_uri_for_sent_in_4x);
00917 
00918 
00919   if (NS_FAILED(rv)) {
00920        MIGRATE_SIMPLE_FILE_PREF_TO_CHAR_PREF(PREF_4X_MAIL_DEFAULT_FCC,identity,SetFccFolder)
00921   }
00922   else {
00923        if (imap_used_uri_for_sent_in_4x) {
00924               MIGRATE_SIMPLE_STR_PREF(PREF_4X_MAIL_IMAP_SENTMAIL_PATH,identity,SetFccFolder)
00925        }
00926        else {
00927               MIGRATE_SIMPLE_FILE_PREF_TO_CHAR_PREF(PREF_4X_MAIL_DEFAULT_FCC,identity,SetFccFolder)
00928        }
00929   }
00930   CONVERT_4X_URI(identity, PR_FALSE /* for news */, username, hostname, DEFAULT_4X_SENT_FOLDER_NAME,GetFccFolder,SetFccFolder,DEFAULT_FCC_FOLDER_PREF_NAME)
00931   CONVERT_4X_URI(identity, PR_FALSE /* for news */, username, hostname, DEFAULT_4X_TEMPLATES_FOLDER_NAME,GetStationeryFolder,SetStationeryFolder,DEFAULT_STATIONERY_FOLDER_PREF_NAME)
00932   CONVERT_4X_URI(identity, PR_FALSE /* for news */, username, hostname, DEFAULT_4X_DRAFTS_FOLDER_NAME,GetDraftFolder,SetDraftFolder,DEFAULT_DRAFT_FOLDER_PREF_NAME)
00933     
00934   return NS_OK;
00935 }
00936 
00937 // caller will free the memory
00938 nsresult
00939 nsMessengerMigrator::Convert4XUri(const char *old_uri, PRBool for_news, const char *aUsername, const char *aHostname, const char *default_folder_name, const char *default_pref_name, char **new_uri)
00940 {
00941   nsresult rv;
00942   *new_uri = nsnull;
00943 
00944   if (!old_uri) {
00945     return NS_ERROR_NULL_POINTER;
00946   }
00947 
00948   nsXPIDLCString default_pref_value;
00949   rv = m_prefs->GetCharPref(default_pref_name, getter_Copies(default_pref_value));
00950   NS_ENSURE_SUCCESS(rv,rv);
00951 
00952   // if the old pref value was "", old_uri will be default value (mail.identity.default.fcc_folder)
00953   // so if old_uri is the default, do some default conversion
00954   if (!nsCRT::strcmp(old_uri, default_pref_value.get())) {
00955        if (!aUsername || !aHostname) {
00956               // if the old uri was "", and we don't know the username or the hostname
00957               // leave it blank.  either someone will be back to fix it,
00958               // SetNewsCopiesAndFolders() and SetMailCopiesAndFolders()
00959               // or we are out of luck.
00960               *new_uri = PR_smprintf("");
00961               return NS_OK;
00962        }
00963 
00964        if ((m_oldMailType == IMAP_4X_MAIL_TYPE) && !for_news) {
00965         nsXPIDLCString escaped_aUsername;
00966         ESCAPE_USER_NAME(escaped_aUsername,aUsername);
00967               *new_uri = PR_smprintf("%s/%s@%s/%s",IMAP_SCHEMA,(const char *)escaped_aUsername,aHostname,default_folder_name);
00968        }
00969        else if ((m_oldMailType == POP_4X_MAIL_TYPE) 
00970 #ifdef HAVE_MOVEMAIL
00971               || (m_oldMailType == MOVEMAIL_4X_MAIL_TYPE)
00972 #endif /* HAVE_MOVEMAIL */
00973               || (m_oldMailType == IMAP_4X_MAIL_TYPE)) {
00974         nsXPIDLCString escaped_aUsername;
00975         ESCAPE_USER_NAME(escaped_aUsername,aUsername);
00976               *new_uri = PR_smprintf("%s/%s@%s/%s",MAILBOX_SCHEMA,(const char *)escaped_aUsername,aHostname,default_folder_name);
00977        }
00978        else {
00979               *new_uri = PR_smprintf("");
00980               return NS_ERROR_UNEXPECTED;
00981        }
00982     return NS_OK;
00983   }
00984 
00985 #ifdef DEBUG_MIGRATOR
00986   printf("old 4.x folder uri = >%s<\n", old_uri);
00987 #endif /* DEBUG_MIGRATOR */
00988 
00989   if (PL_strncasecmp(IMAP_SCHEMA,old_uri,IMAP_SCHEMA_LENGTH) == 0) {
00990        nsXPIDLCString hostname;
00991        nsXPIDLCString username;
00992 
00993     nsCOMPtr<nsIURI> uri;
00994     rv = NS_NewURI(getter_AddRefs(uri), nsDependentCString(old_uri));
00995     if (NS_FAILED(rv)) return rv;
00996 
00997     rv = uri->GetHost(hostname);
00998     if (NS_FAILED(rv)) return rv;
00999 
01000     rv = uri->GetUsername(username);
01001     if (NS_FAILED(rv)) return rv;
01002 
01003     // in 4.x, mac and windows stored the URI as IMAP://<hostname> 
01004        // if the URI was the default folder on the server.
01005        // If it wasn't the default folder, they would have stored it as
01006        if (username.IsEmpty()) {
01007               char *imap_username = nsnull;
01008               char *prefname = nsnull;
01009               prefname = PR_smprintf("mail.imap.server.%s.userName", hostname.get());
01010               if (!prefname) return NS_ERROR_FAILURE;
01011 
01012               rv = m_prefs->GetCharPref(prefname, &imap_username);
01013               PR_FREEIF(prefname);
01014               if (NS_FAILED(rv) || !imap_username || !*imap_username) {
01015                      *new_uri = PR_smprintf("");
01016                      return NS_ERROR_FAILURE;
01017               }
01018               else {
01019                      // new_uri = imap://<username>@<hostname>/<folder name>
01020 #ifdef DEBUG_MIGRATOR
01021                      printf("new_uri = %s/%s@%s/%s\n",IMAP_SCHEMA, imap_username, hostname.get(), default_folder_name);
01022 #endif /* DEBUG_MIGRATOR */
01023                      *new_uri = PR_smprintf("%s/%s@%s/%s",IMAP_SCHEMA, imap_username, hostname.get(), default_folder_name);
01024                      return NS_OK;      
01025               }
01026     }
01027     else {
01028               // IMAP uri's began with "IMAP:/".  we need that to be "imap:/"
01029     // 4.x escapes imap uri in case folder names contain spaces. For example:
01030     //   "imap://qatest20@nsmail-2/Folders%2FJan%20Sent"
01031     // and it needs to be converted to:
01032     //   "imap://qatest20@nsmail-2/Folders/Jan Sent"
01033     // ie, we need to unescape the folder names.
01034 #ifdef DEBUG_MIGRATOR
01035               printf("new_uri = %s%s\n",IMAP_SCHEMA,old_uri+IMAP_SCHEMA_LENGTH);
01036 #endif /* DEBUG_MIGRATOR */
01037 
01038     char *unescaped_uri = nsCRT::strdup(old_uri);
01039     nsUnescape(unescaped_uri);
01040     *new_uri = PR_smprintf("%s%s",IMAP_SCHEMA,unescaped_uri+IMAP_SCHEMA_LENGTH);
01041     nsCRT::free(unescaped_uri);
01042               return NS_OK;
01043        }
01044   }
01045 
01046   char *usernameAtHostname = nsnull;
01047   nsCOMPtr <nsIFileSpec> mail_dir;
01048   char *mail_directory_value = nsnull;
01049   rv = m_prefs->GetComplexValue(PREF_PREMIGRATION_MAIL_DIRECTORY, NS_GET_IID(nsIFileSpec), getter_AddRefs(mail_dir));
01050   if (NS_SUCCEEDED(rv)) {
01051        rv = mail_dir->GetUnixStyleFilePath(&mail_directory_value);
01052   }
01053   if (NS_FAILED(rv) || !mail_directory_value || !*mail_directory_value) {
01054 #ifdef DEBUG_MIGRATOR
01055     printf("%s was not set, attempting to use %s instead.\n",PREF_PREMIGRATION_MAIL_DIRECTORY,PREF_MAIL_DIRECTORY);
01056 #endif
01057     PR_FREEIF(mail_directory_value);
01058 
01059     rv = m_prefs->GetComplexValue(PREF_MAIL_DIRECTORY, NS_GET_IID(nsIFileSpec), getter_AddRefs(mail_dir));
01060     if (NS_SUCCEEDED(rv)) {
01061        rv = mail_dir->GetUnixStyleFilePath(&mail_directory_value);
01062     } 
01063 
01064     if (NS_FAILED(rv) || !mail_directory_value || !*mail_directory_value) {
01065       NS_ASSERTION(0,"failed to get a base value for the mail.directory");
01066       return NS_ERROR_UNEXPECTED;
01067     }
01068   }
01069 
01070   if (m_oldMailType == POP_4X_MAIL_TYPE) {
01071     nsXPIDLCString pop_username;
01072     nsXPIDLCString pop_hostname;
01073 
01074     rv = m_prefs->GetCharPref(PREF_4X_MAIL_POP_NAME, getter_Copies(pop_username));
01075     if (NS_FAILED(rv)) return rv;
01076 
01077     rv = m_prefs->GetCharPref(PREF_4X_NETWORK_HOSTS_POP_SERVER, getter_Copies(pop_hostname));
01078     if (NS_FAILED(rv)) return rv;
01079 
01080     // Need to escape hostname in case it contains spaces.
01081     nsXPIDLCString escaped_pop_username, escaped_pop_hostname;
01082     ESCAPE_USER_NAME(escaped_pop_hostname, pop_hostname);
01083     ESCAPE_USER_NAME(escaped_pop_username,pop_username);
01084 
01085     usernameAtHostname = PR_smprintf("%s@%s", escaped_pop_username.get(), escaped_pop_hostname.get());
01086   }
01087   else if (m_oldMailType == IMAP_4X_MAIL_TYPE) {
01088     // Need to escape hostname in case it contains spaces.
01089     nsXPIDLCString escaped_localfolder_hostname;
01090     ESCAPE_USER_NAME(escaped_localfolder_hostname,mLocalFoldersHostname.get());
01091     usernameAtHostname = PR_smprintf("%s@%s",LOCAL_MAIL_FAKE_USER_NAME, escaped_localfolder_hostname.get());
01092   }
01093 #ifdef HAVE_MOVEMAIL
01094   else if (m_oldMailType == MOVEMAIL_4X_MAIL_TYPE) {
01095        nsXPIDLCString movemail_username;
01096 
01097        rv = m_prefs->GetCharPref(PREF_4X_MAIL_POP_NAME, getter_Copies(movemail_username));
01098        if (NS_FAILED(rv)) return rv; 
01099        
01100     nsXPIDLCString escaped_movemail_username;
01101 
01102     ESCAPE_USER_NAME(escaped_movemail_username,movemail_username);
01103 
01104        usernameAtHostname = PR_smprintf("%s@%s",(const char *)escaped_movemail_username,MOVEMAIL_FAKE_HOST_NAME);
01105   }
01106 #endif /* HAVE_MOVEMAIL */
01107   else {
01108 #ifdef DEBUG_MIGRATOR
01109     printf("Unrecognized server type %d\n", m_oldMailType);
01110 #endif
01111     return NS_ERROR_UNEXPECTED;
01112   }
01113 
01114   const char *folderPath;
01115 
01116   // mail_directory_value is already in UNIX style at this point...
01117   if (PL_strncasecmp(MAILBOX_SCHEMA,old_uri,MAILBOX_SCHEMA_LENGTH) == 0) {
01118 #ifdef DEBUG_MIGRATOR
01119        printf("turn %s into %s/%s/(%s - %s)\n",old_uri,MAILBOX_SCHEMA,usernameAtHostname,old_uri + MAILBOX_SCHEMA_LENGTH,mail_directory_value);
01120 #endif
01121        // the extra -1 is because in 4.x, we had this:
01122        // mailbox:<PATH> instead of mailbox:/<PATH> 
01123        folderPath = old_uri + MAILBOX_SCHEMA_LENGTH + PL_strlen(mail_directory_value) -1;
01124   }
01125   else {
01126 #ifdef DEBUG_MIGRATOR
01127     printf("turn %s into %s/%s/(%s - %s)\n",old_uri,MAILBOX_SCHEMA,usernameAtHostname,old_uri,mail_directory_value);
01128 #endif
01129        folderPath = old_uri + PL_strlen(mail_directory_value);
01130   }
01131   
01132 
01133   // if folder path is "", then the URI was mailbox:/<foobar>
01134   // and the directory pref was <foobar>
01135   // this meant it was reall <foobar>/<default folder name>
01136   // this insanity only happened on mac and windows.
01137   // Need to escape spaces in folder name (ie, "A Folder" --> "A%20Folder").
01138   if (!folderPath || !*folderPath) {
01139     nsXPIDLCString escaped_default_folder;
01140     ESCAPE_FOLDER_NAME(escaped_default_folder, default_folder_name);
01141     *new_uri = PR_smprintf("%s/%s/%s",MAILBOX_SCHEMA,usernameAtHostname, escaped_default_folder.get());
01142   }
01143   else {
01144        // if the folder path starts with a /, we don't need to add one.
01145        // the reason for this is on UNIX, we store mail.directory as "/home/sspitzer/nsmail"
01146        // but on windows, its "C:\foo\bar\mail"
01147     // In 4.x if the local folder names have hierarchy in it then the uri is like:
01148     //   "/My Folders.sbd/New Drafts#1"
01149     // and it needs to be converted to:
01150     //   "/My%20Folders/New%20Drafts%231"
01151     // ie, we need to get rid of all ".sbd" and then escape the URIs (ie, #->%23).
01152     nsCAutoString clean_folderPath(folderPath);
01153     clean_folderPath.ReplaceSubstring(".sbd/", "/");
01154     nsXPIDLCString escaped_folderPath;
01155     ESCAPE_FOLDER_NAME(escaped_folderPath,clean_folderPath.get());
01156     *new_uri = PR_smprintf("%s/%s%s%s",MAILBOX_SCHEMA,usernameAtHostname,(folderPath[0] == '/')?"":"/",escaped_folderPath.get());
01157   }
01158 
01159   if (!*new_uri) {
01160 #ifdef DEBUG_MIGRATOR
01161     printf("failed to convert 4.x uri: %s\n", old_uri);
01162 #endif
01163     NS_ASSERTION(0,"uri conversion code not complete");
01164     return NS_ERROR_FAILURE;
01165   }
01166 
01167   PR_FREEIF(usernameAtHostname);
01168   PR_FREEIF(mail_directory_value);
01169 
01170   return NS_OK;
01171 }
01172 
01173 nsresult
01174 nsMessengerMigrator::MigrateLocalMailAccount() 
01175 {
01176   nsresult rv;
01177   nsCOMPtr<nsIMsgAccountManager> accountManager = 
01178            do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
01179   if (NS_FAILED(rv)) return rv;
01180 
01181   // create the server
01182   // "none" is the type we use for migrating 4.x "Local Mail"
01183   nsCOMPtr<nsIMsgIncomingServer> server;
01184   rv = accountManager->CreateIncomingServer(LOCAL_MAIL_FAKE_USER_NAME,
01185                             mLocalFoldersHostname.get(),
01186                             "none", getter_AddRefs(server));
01187   NS_ENSURE_SUCCESS(rv,rv);
01188 
01189   // now upgrade all the prefs
01190   // some of this ought to be moved out into the NONE implementation
01191   nsCOMPtr<nsINoIncomingServer> noServer;
01192   noServer = do_QueryInterface(server, &rv);
01193   if (NS_FAILED(rv)) return rv;
01194 
01195   // create the directory structure for old 4.x "Local Mail"
01196   // under <profile dir>/Mail/Local Folders or
01197   // <"mail.directory" pref>/Local Folders 
01198   nsCOMPtr<nsIFile> mailDir;
01199   nsFileSpec dir;
01200   PRBool dirExists;
01201 
01202   // if the "mail.directory" pref is set, use that.
01203   // if they used -installer, this pref will point to where their files got copied
01204   nsCOMPtr<nsILocalFile> localFile;
01205   rv = m_prefs->GetComplexValue(PREF_MAIL_DIRECTORY, NS_GET_IID(nsILocalFile), getter_AddRefs(localFile));
01206   if (NS_SUCCEEDED(rv))
01207     mailDir = localFile;
01208   
01209   if (!mailDir) {
01210     // we want <profile>/Mail
01211     rv = NS_GetSpecialDirectory(NS_APP_MAIL_50_DIR, getter_AddRefs(mailDir));
01212     if (NS_FAILED(rv)) return rv;
01213   }
01214 
01215   rv = mailDir->Exists(&dirExists);
01216   if (NS_SUCCEEDED(rv) && !dirExists)
01217     rv = mailDir->Create(nsIFile::DIRECTORY_TYPE, 0775);
01218   if (NS_FAILED(rv)) return rv;  
01219     
01220   nsCOMPtr<nsIFileSpec> mailDirSpec;
01221   
01222   // Convert the nsILocalFile into an nsIFileSpec
01223   // TODO: convert users of nsIFileSpec to nsILocalFile
01224   // and avoid this step.
01225   rv = NS_NewFileSpecFromIFile(mailDir, getter_AddRefs(mailDirSpec));
01226   if (NS_FAILED(rv)) return rv;
01227 
01228   // set the default local path for "none"
01229   rv = server->SetDefaultLocalPath(mailDirSpec);
01230   if (NS_FAILED(rv)) return rv;
01231 
01232   // set the local path for this "none" server
01233 
01234   // get the migration mode for mail
01235   PRBool copyMailFileInMigration = PR_TRUE;
01236   rv = m_prefs->GetBoolPref(PREF_MIGRATION_MODE_FOR_MAIL, &copyMailFileInMigration);
01237   if (NS_FAILED(rv))
01238     return rv;
01239   if (copyMailFileInMigration)
01240   {
01241     // we need to set this to <profile>/Mail/Local Folders, because that's where
01242     // the 4.x "Local Mail" (when using imap) got copied.
01243     // it would be great to use the server key, but we don't know it
01244     // when we are copying of the mail.
01245     rv = mailDirSpec->AppendRelativeUnixPath(mLocalFoldersHostname.get());
01246     if (NS_FAILED(rv)) return rv; 
01247   }
01248   rv = server->SetLocalPath(mailDirSpec);
01249   if (NS_FAILED(rv)) return rv;
01250     
01251   rv = mailDirSpec->Exists(&dirExists);
01252   if (!dirExists) {
01253     mailDirSpec->CreateDir();
01254   }
01255   
01256   // we don't want "nobody at Local Folders" to show up in the
01257   // folder pane, so we set the pretty name to "Local Folders"
01258   server->SetPrettyName(mLocalFoldersName.get());
01259   
01260   // pass the "Local Folders" server so the send later uri pref 
01261   // will be "mailbox://nobody@Local Folders/Unsent Messages"
01262   rv = SetSendLaterUriPref(server);
01263   if (NS_FAILED(rv)) return rv;
01264 
01265   // copy the default templates into the Templates folder
01266   nsCOMPtr <nsINoIncomingServer> noneServer;
01267   noneServer = do_QueryInterface(server, &rv);
01268   if (NS_FAILED(rv)) return rv;
01269   if (!noneServer) return NS_ERROR_FAILURE;
01270   rv = noneServer->CopyDefaultMessages("Templates",mailDirSpec);
01271   if (NS_FAILED(rv)) return rv;
01272  
01273   // Create an account when valid server values are established.
01274   // This will keep the status of accounts sane by avoiding the addition of incomplete accounts. 
01275   nsCOMPtr<nsIMsgAccount> account;
01276   rv = accountManager->CreateAccount(getter_AddRefs(account));
01277   if (NS_FAILED(rv)) return rv;
01278 
01279   // notice, no identity for local mail
01280   // hook the server to the account 
01281   // after we set the server's local path
01282   // (see bug #66018)
01283   rv = account->SetIncomingServer(server);
01284   if (NS_FAILED(rv)) return rv;
01285 
01286   // remember this as the local folders server
01287   rv = accountManager->SetLocalFoldersServer(server);
01288   if (NS_FAILED(rv)) return rv;
01289 
01290   return NS_OK;
01291 }
01292 
01293 #ifdef HAVE_MOVEMAIL
01294 nsresult
01295 nsMessengerMigrator::MigrateMovemailAccount(nsIMsgIdentity *identity)
01296 {
01297   nsresult rv;
01298   
01299   nsCOMPtr<nsIMsgIncomingServer> server;
01300   
01301   nsCOMPtr<nsIMsgAccountManager> accountManager = 
01302            do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
01303   if (NS_FAILED(rv)) return rv;
01304 
01305   // get the pop username
01306   // movemail used the pop username in 4.x
01307   nsXPIDLCString username;
01308   rv = m_prefs->GetCharPref(PREF_4X_MAIL_POP_NAME, getter_Copies(username));
01309   if (NS_FAILED(rv)) return rv;
01310 
01311   //
01312   // create the server
01313   //
01314   rv = accountManager->CreateIncomingServer(username, MOVEMAIL_FAKE_HOST_NAME,
01315                             "movemail", getter_AddRefs(server));
01316   NS_ENSURE_SUCCESS(rv,rv);
01317 
01318   // create the identity
01319   nsCOMPtr<nsIMsgIdentity> copied_identity;
01320   rv = accountManager->CreateIdentity(getter_AddRefs(copied_identity));
01321   if (NS_FAILED(rv)) return rv;
01322 
01323   // now upgrade all the prefs
01324   nsCOMPtr <nsIFileSpec> mailDir;
01325   nsFileSpec dir;
01326   PRBool dirExists;
01327 
01328   rv = MigrateOldMailPrefs(server);
01329   if (NS_FAILED(rv)) return rv;
01330 
01331   // if they used -installer, this pref will point to where their files got copied
01332   rv = m_prefs->GetComplexValue(PREF_MAIL_DIRECTORY, NS_GET_IID(nsIFileSpec), getter_AddRefs(mailDir));
01333   // create the directory structure for old 4.x pop mail
01334   // under <profile dir>/Mail/movemail or
01335   // <"mail.directory" pref>/movemail
01336   //
01337   // if the "mail.directory" pref is set, use that.
01338   if (NS_FAILED(rv)) {
01339     // we wan't <profile>/Mail
01340     nsCOMPtr<nsIFile> aFile;
01341     
01342     rv = NS_GetSpecialDirectory(NS_APP_MAIL_50_DIR, getter_AddRefs(aFile));
01343     if (NS_FAILED(rv)) return rv;
01344 
01345     NS_NewFileSpecFromIFile(aFile, getter_AddRefs(mailDir));
01346     if (NS_FAILED(rv)) return rv;
01347   }
01348 
01349   // set the default local path for "none" (eventually, "movemail")
01350   rv = server->SetDefaultLocalPath(mailDir);
01351   if (NS_FAILED(rv)) return rv;
01352 
01353   rv = mailDir->Exists(&dirExists);
01354   if (!dirExists) {
01355     mailDir->CreateDir();
01356   }
01357 
01358   // we want .../Mail/movemail, not .../Mail
01359   rv = mailDir->AppendRelativeUnixPath(MOVEMAIL_FAKE_HOST_NAME);
01360   if (NS_FAILED(rv)) return rv;
01361   
01362   // set the local path for this "none" (eventually, "movemail" server)
01363   rv = server->SetLocalPath(mailDir);
01364   if (NS_FAILED(rv)) return rv;
01365     
01366   rv = mailDir->Exists(&dirExists);
01367   if (!dirExists) {
01368     mailDir->CreateDir();
01369   }
01370 
01371   // Create an account when valid server and identity values are established.
01372   // This will keep the status of accounts sane by avoiding the addition of incomplete accounts. 
01373   nsCOMPtr<nsIMsgAccount> account;
01374   rv = accountManager->CreateAccount(getter_AddRefs(account));
01375   if (NS_FAILED(rv)) return rv;
01376     
01377   // hook the server to the account 
01378   // before setting the copies and folder prefs
01379   // (see bug #31904)
01380   // but after we set the server's local path
01381   // (see bug #66018)
01382   account->SetIncomingServer(server);
01383   account->AddIdentity(copied_identity);
01384 
01385   // make this new identity a copy of the identity
01386   // that we created out of the 4.x prefs
01387   rv = copied_identity->Copy(identity);
01388   if (NS_FAILED(rv)) return rv;
01389 
01390   // XXX: this probably won't work yet...
01391   // set the cc and fcc values
01392   rv = SetMailCopiesAndFolders(copied_identity, (const char *)username, MOVEMAIL_FAKE_HOST_NAME);
01393   if (NS_FAILED(rv)) return rv;
01394   
01395   // pass the server so the send later uri pref 
01396   // will be something like "mailbox://sspitzer@movemail/Unsent Messages"
01397   rv = SetSendLaterUriPref(server);
01398   if (NS_FAILED(rv)) return rv;
01399 
01400   // we could only have one movemail account in 4.x, so we make it the default in 5.0
01401   rv = accountManager->SetDefaultAccount(account);
01402   return rv;
01403 }
01404 #endif /* HAVE_MOVEMAIL */
01405 
01406 nsresult
01407 nsMessengerMigrator::MigratePopAccount(nsIMsgIdentity *identity)
01408 {
01409   nsresult rv;
01410   nsCOMPtr<nsIMsgAccountManager> accountManager = 
01411            do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
01412   if (NS_FAILED(rv)) return rv;
01413 
01414   nsCOMPtr<nsIMsgIncomingServer> server;
01415 
01416   // get the pop username
01417   nsXPIDLCString username;
01418   rv = m_prefs->GetCharPref(PREF_4X_MAIL_POP_NAME, getter_Copies(username));
01419   if (NS_FAILED(rv)) return rv;
01420 
01421   // get the hostname and port
01422   nsXPIDLCString hostAndPort;
01423   rv = m_prefs->GetCharPref(PREF_4X_NETWORK_HOSTS_POP_SERVER,
01424                              getter_Copies(hostAndPort));
01425   if (NS_FAILED(rv)) return rv;
01426 
01427   PRInt32 port = -1;
01428   nsCAutoString hostname(hostAndPort);
01429   PRInt32 colonPos = hostname.FindChar(':');
01430   if (colonPos != -1) {
01431         hostname.Truncate(colonPos);
01432         
01433         // migrate the port from hostAndPort
01434         nsCAutoString portStr(hostAndPort + colonPos);
01435         PRInt32 err;
01436         port = portStr.ToInteger(&err);
01437         NS_ASSERTION(err == 0, "failed to get the port\n");
01438         if (err != 0) port=-1;
01439   }
01440 
01441   //
01442   // create the server
01443   //
01444   rv = accountManager->CreateIncomingServer(username.get(), hostname.get(), "pop3",
01445                             getter_AddRefs(server));
01446   NS_ENSURE_SUCCESS(rv,rv);
01447 
01448   // if we got a valid port from above, set it here
01449   if (port > 0) {
01450     server->SetPort(port);
01451   }
01452   
01453   // now upgrade all the prefs
01454   nsCOMPtr <nsIFile> mailDir;
01455   nsFileSpec dir;
01456   PRBool dirExists;
01457 
01458 #ifdef DEBUG_MIGRATOR
01459   PRInt32 portValue;
01460   rv = server->GetPort(&portValue);
01461   printf("HOSTNAME = %s\n", hostname.get());
01462   printf("PORT = %d\n", portValue);
01463 #endif /* DEBUG_MIGRATOR */
01464 
01465   rv = MigrateOldMailPrefs(server);
01466   if (NS_FAILED(rv)) return rv;
01467 
01468   // create the directory structure for old 4.x pop mail
01469   // under <profile dir>/Mail/<pop host name> or
01470   // <"mail.directory" pref>/<pop host name>
01471   //
01472   // if the "mail.directory" pref is set, use that.
01473   // if they used -installer, this pref will point to where their files got copied
01474   nsCOMPtr<nsILocalFile> localFile;
01475   rv = m_prefs->GetComplexValue(PREF_MAIL_DIRECTORY, NS_GET_IID(nsILocalFile), getter_AddRefs(localFile));
01476   if (NS_SUCCEEDED(rv))
01477     mailDir = localFile;
01478   
01479   if (!mailDir) {
01480     // we wan't <profile>/Mail
01481     rv = NS_GetSpecialDirectory(NS_APP_MAIL_50_DIR, getter_AddRefs(mailDir));
01482     if (NS_FAILED(rv)) return rv;
01483   }
01484 
01485   rv = mailDir->Exists(&dirExists);
01486   if (NS_SUCCEEDED(rv) && !dirExists)
01487     rv = mailDir->Create(nsIFile::DIRECTORY_TYPE, 0775);
01488   if (NS_FAILED(rv)) return rv;
01489   
01490   nsCOMPtr<nsIFileSpec> mailDirSpec;
01491   
01492   // Convert the nsILocalFile into an nsIFileSpec
01493   // TODO: convert users os nsIFileSpec to nsILocalFile
01494   // and avoid this step.
01495   rv = NS_NewFileSpecFromIFile(mailDir, getter_AddRefs(mailDirSpec));
01496   if (NS_FAILED(rv)) return rv;
01497 
01498   // set the default local path for "pop3"
01499   rv = server->SetDefaultLocalPath(mailDirSpec);
01500   if (NS_FAILED(rv)) return rv;
01501 
01502   rv = mailDirSpec->Exists(&dirExists);
01503   if (!dirExists) {
01504     mailDirSpec->CreateDir();
01505   }
01506 
01507   // we want .../Mail/<hostname>, not .../Mail
01508   // Only host name is required 
01509   rv = mailDirSpec->AppendRelativeUnixPath(hostname.get());
01510   if (NS_FAILED(rv)) return rv;
01511   
01512   // set the local path for this "pop3" server
01513   rv = server->SetLocalPath(mailDirSpec);
01514   if (NS_FAILED(rv)) return rv;
01515     
01516   rv = mailDirSpec->Exists(&dirExists);
01517   if (!dirExists) {
01518     mailDirSpec->CreateDir();
01519   }
01520     
01521   // pass the pop server so the send later uri pref 
01522   // will be something like "mailbox://sspitzer@tintin/Unsent Messages"
01523   rv = SetSendLaterUriPref(server);
01524   if (NS_FAILED(rv)) return rv;
01525 
01526   // Set check for new mail option for default account to TRUE 
01527   rv = server->SetLoginAtStartUp(PR_TRUE);
01528 
01529   // create the identity
01530   nsCOMPtr<nsIMsgIdentity> copied_identity;
01531   rv = accountManager->CreateIdentity(getter_AddRefs(copied_identity));
01532   if (NS_FAILED(rv)) return rv;
01533 
01534   // Create an account when valid server and identity values are established.
01535   // This will keep the status of accounts sane by avoiding the addition of incomplete accounts. 
01536   nsCOMPtr<nsIMsgAccount> account;
01537   rv = accountManager->CreateAccount(getter_AddRefs(account));
01538   if (NS_FAILED(rv)) return rv;
01539 
01540   // hook the server to the account 
01541   // before setting the copies and folder prefs
01542   // (see bug #31904)
01543   // but after we set the server's local path
01544   // (see bug #66018)
01545   account->SetIncomingServer(server);
01546   account->AddIdentity(copied_identity);
01547 
01548   // we could only have one pop account in 4.x, so we make it the default in 5.0
01549   rv = accountManager->SetDefaultAccount(account);
01550   NS_ENSURE_SUCCESS(rv, rv);
01551 
01552   // make this new identity a copy of the identity
01553   // that we created out of the 4.x prefs
01554   rv = copied_identity->Copy(identity);
01555   if (NS_FAILED(rv)) return rv;
01556 
01557   rv = SetMailCopiesAndFolders(copied_identity, username.get(), hostname.get());
01558   if (NS_FAILED(rv)) return rv;
01559   
01560   return rv;
01561 }
01562 nsresult 
01563 nsMessengerMigrator::SetSendLaterUriPref(nsIMsgIncomingServer *server)
01564 {
01565        nsresult rv;
01566 
01567        // set "mail.default_sendlater_uri" to something like
01568        // mailbox://nobody@Local Folders/Unsent Messages"
01569        // mailbox://sspitzer@tintin/Unsent Messages"
01570        //
01571        // note, the schema is mailbox:/ 
01572        // Unsent is an off-line thing, and that needs to be
01573        // on the disk, not on an imap server.
01574        nsXPIDLCString username;
01575        rv = server->GetUsername(getter_Copies(username));
01576        if (NS_FAILED(rv)) return rv;
01577 
01578        nsXPIDLCString hostname;
01579        rv = server->GetHostName(getter_Copies(hostname));
01580        if (NS_FAILED(rv)) return rv;
01581 
01582   nsXPIDLCString escaped_username, escaped_hostname;
01583   ESCAPE_USER_NAME(escaped_hostname, hostname);
01584   ESCAPE_USER_NAME(escaped_username,username);
01585 
01586        char *sendLaterUriStr = nsnull;
01587        sendLaterUriStr = PR_smprintf("%s/%s@%s/%s", MAILBOX_SCHEMA, escaped_username.get(), escaped_hostname.get(), UNSENT_MESSAGES_FOLDER_NAME);
01588        m_prefs->SetCharPref(PREF_MAIL_DEFAULT_SENDLATER_URI, sendLaterUriStr);
01589        PR_FREEIF(sendLaterUriStr);
01590 
01591        return NS_OK;
01592 }
01593 
01594 nsresult
01595 nsMessengerMigrator::MigrateOldMailPrefs(nsIMsgIncomingServer * server)
01596 {
01597   nsresult rv;
01598 
01599   // don't migrate the remember password pref.  see bug #42216 
01600   //MIGRATE_SIMPLE_BOOL_PREF(PREF_4X_MAIL_REMEMBER_PASSWORD,server,SetRememberPassword)
01601   rv = server->SetRememberPassword(PR_FALSE);
01602   if (NS_FAILED(rv)) return rv;
01603   
01604   rv = server->SetPassword(nsnull);
01605   if (NS_FAILED(rv)) return rv;
01606 
01607   MIGRATE_SIMPLE_BOOL_PREF(PREF_4X_MAIL_CHECK_NEW_MAIL,server,SetDoBiff)
01608   MIGRATE_SIMPLE_INT_PREF(PREF_4X_MAIL_CHECK_TIME,server,SetBiffMinutes)
01609   MIGRATE_SIMPLE_BOOL_PREF(PREF_4X_MAIL_POP3_GETS_NEW_MAIL,server,SetDownloadOnBiff)
01610 
01611   nsCOMPtr<nsIPop3IncomingServer> popServer;
01612   popServer = do_QueryInterface(server, &rv);
01613   if (NS_SUCCEEDED(rv) && popServer) {
01614          MIGRATE_SIMPLE_BOOL_PREF(PREF_4X_MAIL_LEAVE_ON_SERVER,popServer,SetLeaveMessagesOnServer)
01615          MIGRATE_SIMPLE_BOOL_PREF(PREF_4X_MAIL_DELETE_MAIL_LEFT_ON_SERVER,popServer,SetDeleteMailLeftOnServer) 
01616   }
01617   else {
01618        // could be a movemail server, in that case do nothing.
01619   }
01620 
01621   return NS_OK;
01622 }
01623 
01624 nsresult
01625 nsMessengerMigrator::MigrateImapAccounts(nsIMsgIdentity *identity)
01626 {
01627   nsresult rv;
01628   char *hostList=nsnull;
01629   rv = getPrefService();
01630   if (NS_FAILED(rv)) return rv;
01631 
01632   rv = m_prefs->GetCharPref(PREF_4X_NETWORK_HOSTS_IMAP_SERVER, &hostList);
01633   if (NS_FAILED(rv)) return rv;
01634   
01635   if (!hostList || !*hostList) return NS_OK;  // NS_ERROR_FAILURE?
01636   
01637   char *token = nsnull;
01638   char *rest = hostList;
01639   nsCAutoString str;
01640 
01641   PRBool isDefaultAccount = PR_TRUE;
01642       
01643   token = nsCRT::strtok(rest, ",", &rest);
01644   while (token && *token) {
01645     str = token;
01646     str.StripWhitespace();
01647     
01648     if (!str.IsEmpty()) {
01649       // str is the hostname
01650       rv = MigrateImapAccount(identity,str.get(),isDefaultAccount);
01651       if  (NS_FAILED(rv)) {
01652         // failed to migrate.  bail.
01653         return rv;
01654       }
01655       str = "";
01656       // the default imap server in 4.x was the first one in the list.
01657       // so after we've seen the first one, the rest are not the default
01658       isDefaultAccount = PR_FALSE;
01659     }
01660     token = nsCRT::strtok(rest, ",", &rest);
01661   }
01662   PR_FREEIF(hostList);
01663   return NS_OK;
01664 }
01665 
01666 nsresult
01667 nsMessengerMigrator::MigrateImapAccount(nsIMsgIdentity *identity, const char *hostAndPort, PRBool isDefaultAccount)
01668 {
01669   nsresult rv;  
01670 
01671   nsCOMPtr<nsIMsgAccountManager> accountManager = 
01672            do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
01673   if (NS_FAILED(rv)) return rv;
01674 
01675   if (!hostAndPort) return NS_ERROR_NULL_POINTER;
01676  
01677   // get the old username
01678   nsXPIDLCString username;
01679   char *imapUsernamePref =
01680     PR_smprintf("mail.imap.server.%s.userName", hostAndPort);
01681   rv = m_prefs->GetCharPref(imapUsernamePref, getter_Copies(username));
01682   PR_FREEIF(imapUsernamePref);
01683   NS_ENSURE_SUCCESS(rv,rv);
01684 
01685   PRBool isSecure = PR_FALSE;
01686   char *imapIsSecurePref = PR_smprintf("mail.imap.server.%s.isSecure", hostAndPort);
01687   rv = m_prefs->GetBoolPref(imapIsSecurePref, &isSecure);
01688   PR_FREEIF(imapIsSecurePref);
01689   NS_ENSURE_SUCCESS(rv,rv);
01690 
01691   // get the old host (and possibly port)
01692   PRInt32 port = -1;
01693   nsCAutoString hostname(hostAndPort);
01694   PRInt32 colonPos = hostname.FindChar(':');
01695   if (colonPos != -1) {
01696        nsCAutoString portStr(hostAndPort + colonPos);
01697        hostname.Truncate(colonPos);
01698        PRInt32 err;
01699     port = portStr.ToInteger(&err);
01700        NS_ASSERTION(err == 0, "failed to get the port\n");
01701     if (err != 0)
01702       port = -1;
01703   }
01704 
01705 
01706   //
01707   // create the server
01708   //
01709   nsCOMPtr<nsIMsgIncomingServer> server;
01710   rv = accountManager->CreateIncomingServer(username.get(), hostname.get(), "imap",
01711                             getter_AddRefs(server));
01712   NS_ENSURE_SUCCESS(rv,rv);
01713 
01714   if (port > 0) {
01715     rv = server->SetPort(port);
01716     NS_ENSURE_SUCCESS(rv,rv);
01717   }
01718   else {
01719     if (isSecure) {
01720       nsCOMPtr <nsIMsgProtocolInfo> protocolInfo = do_GetService("@mozilla.org/messenger/protocol/info;1?type=imap", &rv);
01721       NS_ENSURE_SUCCESS(rv,rv);
01722 
01723       rv = protocolInfo->GetDefaultServerPort(PR_TRUE, &port);
01724       NS_ENSURE_SUCCESS(rv,rv);
01725 
01726       rv = server->SetPort(port);
01727       NS_ENSURE_SUCCESS(rv,rv);
01728     }
01729   }
01730 
01731   rv = server->SetIsSecure(isSecure);
01732   NS_ENSURE_SUCCESS(rv,rv);
01733 
01734   // Generate unique pretty name for the account. It is important that this function
01735   // is called here after all port settings are taken care of.
01736   // Port values, if not default, will be used as a part of pretty name.
01737   nsXPIDLString prettyName;
01738   rv = server->GeneratePrettyNameForMigration(getter_Copies(prettyName));  
01739   NS_ENSURE_SUCCESS(rv,rv);
01740 
01741   // Set pretty name for the account with this server
01742   if (prettyName.get())
01743   {
01744     rv = server->SetPrettyName(prettyName);
01745     NS_ENSURE_SUCCESS(rv,rv);
01746   }
01747 
01748 #ifdef DEBUG_MIGRATOR
01749   PRInt32 portValue;
01750   rv = server->GetPort(&portValue);
01751   printf("HOSTNAME = %s\n", hostname.get());
01752   printf("PORT = %d\n", portValue);
01753 #endif /* DEBUG_MIGRATOR */
01754 
01755   // now upgrade all the prefs
01756 
01757   rv = MigrateOldImapPrefs(server, hostAndPort);
01758   if (NS_FAILED(rv)) return rv;
01759 
01760   nsCOMPtr <nsIFile> imapMailDir;
01761   nsFileSpec dir;
01762   PRBool dirExists;
01763 
01764   // if they used -installer, this pref will point to where their files got copied
01765   // if the "mail.imap.root_dir" pref is set, use that.
01766   nsCOMPtr<nsILocalFile> localFile;
01767   rv = m_prefs->GetComplexValue(PREF_IMAP_DIRECTORY, NS_GET_IID(nsILocalFile), getter_AddRefs(localFile));
01768   if (NS_SUCCEEDED(rv))
01769     imapMailDir = localFile;
01770   
01771   if (!imapMailDir) {
01772     // we want <profile>/ImapMail
01773     rv = NS_GetSpecialDirectory(NS_APP_IMAP_MAIL_50_DIR, getter_AddRefs(imapMailDir));
01774     if (NS_FAILED(rv)) return rv;
01775   }
01776 
01777   rv = imapMailDir->Exists(&dirExists);
01778   if (NS_SUCCEEDED(rv) && !dirExists)
01779     rv = imapMailDir->Create(nsIFile::DIRECTORY_TYPE, 0775);
01780   if (NS_FAILED(rv)) return rv;
01781   
01782   nsCOMPtr<nsIFileSpec> imapMailDirSpec;
01783 
01784   // Convert the nsILocalFile into an nsIFileSpec
01785   // TODO: convert users os nsIFileSpec to nsILocalFile
01786   // and avoid this step.
01787   rv = NS_NewFileSpecFromIFile(imapMailDir, getter_AddRefs(imapMailDirSpec));
01788   if (NS_FAILED(rv)) return rv;
01789 
01790   // we only need to do this once
01791   if (!m_alreadySetImapDefaultLocalPath) {
01792     // set the default local path for "imap"
01793     rv = server->SetDefaultLocalPath(imapMailDirSpec);
01794     if (NS_FAILED(rv)) return rv;
01795 
01796     m_alreadySetImapDefaultLocalPath = PR_TRUE;
01797   }
01798   
01799   // we want .../ImapMail/<hostname>, not .../ImapMail
01800   rv = imapMailDirSpec->AppendRelativeUnixPath(hostname.get());
01801   if (NS_FAILED(rv)) return rv;
01802 
01803   // set the local path for this "imap" server
01804   rv = server->SetLocalPath(imapMailDirSpec);
01805   if (NS_FAILED(rv)) return rv;
01806    
01807   rv = imapMailDirSpec->Exists(&dirExists);
01808   if (!dirExists) {
01809     imapMailDirSpec->CreateDir();
01810   }
01811   
01812   // create the identity
01813   nsCOMPtr<nsIMsgIdentity> copied_identity;
01814   rv = accountManager->CreateIdentity(getter_AddRefs(copied_identity));
01815   if (NS_FAILED(rv)) return rv;
01816 
01817   // Create an account when valid server and identity values are established.
01818   // This will keep the status of accounts sane by avoiding the addition of incomplete accounts. 
01819   nsCOMPtr<nsIMsgAccount> account;
01820   rv = accountManager->CreateAccount(getter_AddRefs(account));
01821   if (NS_FAILED(rv)) return rv;
01822 
01823   // hook the server to the account 
01824   // before setting the copies and folder prefs
01825   // (see bug #31904)
01826   // but after we set the server's local path
01827   // (see bug #66018)
01828   account->SetIncomingServer(server);
01829   account->AddIdentity(copied_identity);
01830 
01831   // make this new identity a copy of the identity
01832   // that we created out of the 4.x prefs
01833   rv = copied_identity->Copy(identity);
01834   if (NS_FAILED(rv)) return rv;
01835   
01836   rv = SetMailCopiesAndFolders(copied_identity, username.get(), hostname.get());
01837   if (NS_FAILED(rv)) return rv;  
01838   
01839  
01840   if (isDefaultAccount) {
01841     rv = accountManager->SetDefaultAccount(account);
01842     if (NS_FAILED(rv)) return rv;
01843 
01844     // Set check for new mail option for default account to TRUE 
01845     rv = server->SetLoginAtStartUp(PR_TRUE);
01846   }
01847 
01848   return NS_OK;
01849 }
01850 
01851 nsresult
01852 nsMessengerMigrator::MigrateOldImapPrefs(nsIMsgIncomingServer *server, const char *hostAndPort)
01853 {
01854   nsresult rv;
01855 
01856   // some of this ought to be moved out into the IMAP implementation
01857   nsCOMPtr<nsIImapIncomingServer> imapServer;
01858   imapServer = do_QueryInterface(server, &rv);
01859   if (NS_FAILED(rv)) return rv;
01860 
01861   // upgrade the msg incoming server prefs
01862   // don't migrate the remember password pref.  see bug #42216 
01863   //MIGRATE_BOOL_PREF("mail.imap.server.%s.remember_password",hostAndPort,server,SetRememberPassword)
01864   rv = server->SetRememberPassword(PR_FALSE);
01865   if (NS_FAILED(rv)) return rv;
01866 
01867   rv = server->SetPassword(nsnull);
01868   if (NS_FAILED(rv)) return rv;
01869 
01870   // upgrade the imap incoming server specific prefs
01871   MIGRATE_BOOL_PREF("mail.imap.server.%s.check_new_mail",hostAndPort,server,SetDoBiff)
01872   MIGRATE_INT_PREF("mail.imap.server.%s.check_time",hostAndPort,server,SetBiffMinutes)
01873   // "mail.imap.new_mail_get_headers" was a global pref across all imap servers in 4.x
01874   // in 5.0, it's per server
01875   MIGRATE_BOOL_PREF("%s","mail.imap.new_mail_get_headers",server,SetDownloadOnBiff)
01876   MIGRATE_STR_PREF("mail.imap.server.%s.admin_url",hostAndPort,imapServer,SetAdminUrl)
01877   MIGRATE_STR_PREF("mail.imap.server.%s.server_sub_directory",hostAndPort,imapServer,SetServerDirectory);
01878   MIGRATE_INT_PREF("mail.imap.server.%s.capability",hostAndPort,imapServer,SetCapabilityPref)
01879   MIGRATE_BOOL_PREF("mail.imap.server.%s.cleanup_inbox_on_exit",hostAndPort,imapServer,SetCleanupInboxOnExit)
01880   MIGRATE_INT_PREF("mail.imap.server.%s.delete_model",hostAndPort,imapServer,SetDeleteModel)
01881   MIGRATE_BOOL_PREF("mail.imap.server.%s.dual_use_folders",hostAndPort,imapServer,SetDualUseFolders)
01882   MIGRATE_BOOL_PREF("mail.imap.server.%s.empty_trash_on_exit",hostAndPort,server,SetEmptyTrashOnExit)
01883   MIGRATE_INT_PREF("mail.imap.server.%s.empty_trash_threshhold",hostAndPort,imapServer,SetEmptyTrashThreshhold)
01884   MIGRATE_STR_PREF("mail.imap.server.%s.namespace.other_users",hostAndPort,imapServer,SetOtherUsersNamespace)
01885   MIGRATE_STR_PREF("mail.imap.server.%s.namespace.personal",hostAndPort,imapServer,SetPersonalNamespace)
01886   MIGRATE_STR_PREF("mail.imap.server.%s.namespace.public",hostAndPort,imapServer,SetPublicNamespace)
01887   MIGRATE_BOOL_PREF("mail.imap.server.%s.offline_download",hostAndPort,imapServer,SetOfflineDownload)
01888   MIGRATE_BOOL_PREF("mail.imap.server.%s.override_namespaces",hostAndPort,imapServer,SetOverrideNamespaces)
01889   MIGRATE_BOOL_PREF("mail.imap.server.%s.using_subscription",hostAndPort,imapServer,SetUsingSubscription)
01890 
01891   return NS_OK;
01892 }
01893 
01894 static PRBool charEndsWith(const char *str, const char *endStr)
01895 {
01896     PRUint32 endStrLen = PL_strlen(endStr);
01897     PRUint32 strLen = PL_strlen(str);
01898    
01899     if (strLen < endStrLen) return PR_FALSE;
01900 
01901     PRUint32 pos = strLen - endStrLen;
01902     if (PL_strncmp(str + pos, endStr, endStrLen) == 0) {
01903         return PR_TRUE;
01904     }
01905     else {
01906         return PR_FALSE;
01907     }
01908 }
01909 
01910 #define ADDRESSBOOK_PREF_NAME_ROOT "ldap_2.servers."
01911 #define ADDRESSBOOK_PREF_NAME_SUFFIX ".filename"
01912 #define ADDRESSBOOK_PREF_CSID_SUFFIX ".csid"
01913 #define ADDRESSBOOK_PREF_VALUE_4x_SUFFIX ".na2"
01914 #define ADDRESSBOOK_PREF_VALUE_5x_SUFFIX ".mab"
01915 #define TEMP_LDIF_FILE_SUFFIX ".ldif"
01916 
01917 #if defined(DEBUG_sspitzer_) || defined(DEBUG_seth_)
01918 #define DEBUG_AB_MIGRATION 1
01919 #endif
01920 
01921 void
01922 nsMessengerMigrator::migrateAddressBookPrefEnum(const char *aPref)
01923 {
01924   nsresult rv = NS_OK;
01925 
01926 #ifdef DEBUG_AB_MIGRATION
01927   printf("investigate pref: %s\n",aPref);
01928 #endif
01929   nsXPIDLCString abFileName;
01930   // we only care about ldap_2.servers.*.filename" prefs
01931   if (!charEndsWith(aPref, ADDRESSBOOK_PREF_NAME_SUFFIX)) return;
01932       
01933   // check for pab without a filename and if so, set it to pab.na2.
01934   // This is an ugly hack for installations that haven't set 
01935   // pab.filename.
01936       rv = m_prefs->GetCharPref(DEFAULT_PAB_FILENAME_PREF_NAME, getter_Copies(abFileName));
01937       if (NS_FAILED(rv))
01938       {
01939         // pab.filename not set - set it to pab.na2 and pretend aPref is it.
01940         m_prefs->SetCharPref(DEFAULT_PAB_FILENAME_PREF_NAME, "pab.na2");
01941         aPref = "ldap_2.servers.pab.filename";
01942       }
01943 
01944   // check if this really is an ldap server, in which case, we're not going to migrate
01945   // the na2 file for now, since it confuses RDF when the import code adds this
01946   // server as a personal address book. I'd like to fix that but it's tricky
01947   // and the .na2 file for ldap servers should only be for offline data.
01948 
01949   nsCAutoString serverPrefName(aPref);
01950   PRInt32 fileNamePos = serverPrefName.Find(".filename");
01951   serverPrefName.Truncate(fileNamePos + 1);
01952   serverPrefName.AppendLiteral("serverName");
01953   nsXPIDLCString serverName;
01954   rv = m_prefs->GetCharPref(serverPrefName.get(), getter_Copies(serverName));
01955   if (NS_SUCCEEDED(rv) && !serverName.IsEmpty())
01956     return; // skip this - it's an ldap server
01957       
01958   rv = m_prefs->GetCharPref(aPref,getter_Copies(abFileName));
01959   NS_ASSERTION(NS_SUCCEEDED(rv),"ab migration failed: failed to get ab filename");
01960   if (NS_FAILED(rv)) return;
01961   
01962   NS_ASSERTION(((const char *)abFileName), "ERROR:  empty addressbook file name");
01963   if (!((const char *)abFileName)) return;
01964 
01965   NS_ASSERTION(PL_strlen((const char *)abFileName),"ERROR:  empty addressbook file name");
01966   if (!(PL_strlen((const char *)abFileName))) return;
01967 
01968 #ifdef DEBUG_AB_MIGRATION
01969   printf("pref value: %s\n",(const char *)abFileName);
01970 #endif /* DEBUG_AB_MIGRATION */
01971   // if this a 5.x addressbook file name, skip it.
01972   if (charEndsWith((const char *)abFileName, ADDRESSBOOK_PREF_VALUE_5x_SUFFIX)) return;
01973     
01974   nsCAutoString abName;
01975   abName = abFileName;
01976   PRInt32 len = abName.Length();
01977   PRInt32 suffixLen = PL_strlen(ADDRESSBOOK_PREF_VALUE_4x_SUFFIX);
01978   NS_ASSERTION(len > suffixLen, "ERROR: bad length of addressbook filename");
01979   if (len <= suffixLen) return;
01980   
01981   abName.SetLength(len - suffixLen);
01982 
01983   // get 5.0 profile root.
01984   nsCOMPtr <nsIFile> ab4xFile;
01985   nsCOMPtr <nsIFileSpec> ab4xFileSpec;
01986   nsCOMPtr <nsIFile> tmpLDIFFile;
01987   nsCOMPtr <nsIFileSpec> tmpLDIFFileSpec;
01988 
01989 #ifdef DEBUG_AB_MIGRATION
01990   printf("turn %s%s into %s%s\n", (const char *)abName,ADDRESSBOOK_PREF_VALUE_4x_SUFFIX,(const char *)abName,TEMP_LDIF_FILE_SUFFIX);
01991 #endif /* DEBUG_AB_MIGRATION */
01992 
01993   rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(ab4xFile));
01994   NS_ASSERTION(NS_SUCCEEDED(rv) && ab4xFile,"ab migration failed: failed to get profile dir");
01995   if (NS_FAILED(rv) || !ab4xFile) return;
01996   
01997   rv = ab4xFile->AppendNative(nsDependentCString(abFileName));
01998   NS_ASSERTION(NS_SUCCEEDED(rv),"ab migration failed:  failed to append filename");
01999   if (NS_FAILED(rv)) return;
02000 
02001   // TODO: Change users of nsIFileSpec to nsIFile and avoid this.
02002   rv = NS_NewFileSpecFromIFile(ab4xFile, getter_AddRefs(ab4xFileSpec));
02003   if (NS_FAILED(rv)) return;
02004 
02005   rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmpLDIFFile));
02006   if (NS_FAILED(rv) || !tmpLDIFFile) return;
02007 
02008   // do the migration in a subdirectory of temp, to prevent 
02009   // collision (between multiple users), deleting TMPDIR
02010   // and privacy issues (where the temp ldif files are readable)
02011   rv = tmpLDIFFile->AppendNative(NS_LITERAL_CSTRING("addr-migrate"));
02012   if (NS_FAILED(rv) || !tmpLDIFFile) return;
02013 
02014   rv = tmpLDIFFile->CreateUnique(nsIFile::DIRECTORY_TYPE, 0700);
02015   if (NS_FAILED(rv) || !tmpLDIFFile) return;
02016 
02017   // TODO: Change users of nsIFileSpec to nsIFile and avoid this.
02018   rv = NS_NewFileSpecFromIFile(tmpLDIFFile, getter_AddRefs(tmpLDIFFileSpec));
02019   if (NS_FAILED(rv)) return;
02020 
02021   // get the csid from the prefs
02022   nsCAutoString csidPrefName;
02023   csidPrefName.AssignLiteral(ADDRESSBOOK_PREF_NAME_ROOT);
02024   csidPrefName += abName; 
02025   csidPrefName.AppendLiteral(ADDRESSBOOK_PREF_CSID_SUFFIX);
02026   nsXPIDLCString csidPrefValue;
02027   rv = m_prefs->GetCharPref(csidPrefName.get(),getter_Copies(csidPrefValue));
02028   if (NS_FAILED(rv)) { 
02029        // if we fail to get the pref value, set it to "", which will
02030        // later cause us to use the system charset
02031        csidPrefValue.Truncate();
02032   }
02033 
02034   nsCOMPtr <nsIAbUpgrader> abUpgrader = do_GetService(NS_AB4xUPGRADER_CONTRACTID, &rv);
02035   NS_ASSERTION(NS_SUCCEEDED(rv) && abUpgrader, "failed to get upgrader");
02036   if (NS_FAILED(rv) || !abUpgrader) return;
02037   rv = abUpgrader->SetCurrentCharset((const char *)csidPrefValue);
02038   NS_ASSERTION(NS_SUCCEEDED(rv), "failed to set the current char set");
02039   if (NS_FAILED(rv)) return;
02040 
02041 // HACK:  I need to rename pab.ldif -> abook.ldif, because a bunch of places are hacked to point to abook.mab, and when I import abook.ldif it will create abook.mab. this is a temporary hack and will go away soon.
02042   if (abName.EqualsLiteral("pab")) {
02043        abName = "abook";
02044   }
02045 
02046   nsCAutoString ldifFileName;
02047   ldifFileName = abName;
02048   ldifFileName.AppendLiteral(TEMP_LDIF_FILE_SUFFIX);
02049   rv = tmpLDIFFileSpec->AppendRelativeUnixPath(ldifFileName.get());
02050   NS_ASSERTION(NS_SUCCEEDED(rv),"ab migration failed: failed to append filename");
02051   if (NS_FAILED(rv)) return;
02052      
02053   nsCOMPtr <nsIAddressBook> ab = do_CreateInstance(NS_ADDRESSBOOK_CONTRACTID, &rv);
02054   NS_ASSERTION(NS_SUCCEEDED(rv) && ab, "failed to get address book");
02055   if (NS_FAILED(rv) || !ab) return;
02056 
02057   rv = ab->ConvertNA2toLDIF(ab4xFileSpec, tmpLDIFFileSpec);
02058   NS_ASSERTION(NS_SUCCEEDED(rv),"ab migration failed: failed to convert na2 to ldif");
02059   if (NS_FAILED(rv)) return;
02060   
02061   rv = ab->Migrate4xAb(tmpLDIFFileSpec, PR_TRUE /* migrating */, PR_FALSE);
02062   NS_ASSERTION(NS_SUCCEEDED(rv),"ab migration filed:  failed to convert ldif to mab\n");
02063   if (NS_FAILED(rv)) return;
02064  
02065   // this sucks.
02066   // ConvertLDIFtoMAB should set this pref value for us. 
02067 #ifdef DEBUG_AB_MIGRATION
02068   printf("set %s the pref to %s%s\n",aPref,(const char *)abName,ADDRESSBOOK_PREF_VALUE_5x_SUFFIX);
02069 #endif /* DEBUG_AB_MIGRATION */
02070   
02071   nsCAutoString newPrefValue;
02072   newPrefValue = abName;
02073   newPrefValue.AppendLiteral(ADDRESSBOOK_PREF_VALUE_5x_SUFFIX);
02074   rv = m_prefs->SetCharPref(aPref,newPrefValue.get());
02075   NS_ASSERTION(NS_SUCCEEDED(rv),"ab migration failed: failed to set pref");
02076   if (NS_FAILED(rv)) return;
02077  
02078 #ifdef DEBUG_AB_MIGRATION
02079   printf("remove the tmp file\n");
02080 #endif /* DEBUG_AB_MIGRATION */
02081   rv = ab4xFile->Remove(PR_FALSE);
02082   NS_ASSERTION(NS_SUCCEEDED(rv),"failed to delete the na2 file");
02083   if (NS_FAILED(rv)) return;
02084   rv = tmpLDIFFile->Remove(PR_TRUE);
02085   NS_ASSERTION(NS_SUCCEEDED(rv),"failed to delete the temp ldif file");
02086   
02087   return;
02088 }
02089 
02090 nsresult 
02091 nsMessengerMigrator::MigrateAddressBookPrefs()
02092 {
02093   nsresult rv;
02094   PRBool autoCompleteAgainstLocalAddressbooks;
02095 
02096   rv = m_prefs->GetBoolPref(PREF_4X_AUTOCOMPLETE_ON_LOCAL_AB, &autoCompleteAgainstLocalAddressbooks);
02097 
02098   if (NS_SUCCEEDED(rv)) {
02099     rv = m_prefs->SetBoolPref(PREF_MOZILLA_AUTOCOMPLETE_ON_LOCAL_AB, autoCompleteAgainstLocalAddressbooks);
02100     NS_ENSURE_SUCCESS(rv,rv);
02101   }
02102   return NS_OK;
02103 }
02104 
02105 nsresult
02106 nsMessengerMigrator::MigrateAddressBooks()
02107 {
02108   nsresult rv = NS_OK;
02109 
02110   nsCOMPtr <nsIAbUpgrader> abUpgrader = do_GetService(NS_AB4xUPGRADER_CONTRACTID, &rv);
02111   if (NS_FAILED(rv) || !abUpgrader) {
02112     printf("the addressbook migrator is only in the commercial builds.\n");
02113     return NS_OK;
02114   }
02115 
02116   PRUint32 num;
02117   char **arr;
02118 
02119   rv = m_prefs->GetChildList(ADDRESSBOOK_PREF_NAME_ROOT, &num, &arr);
02120   if (NS_SUCCEEDED(rv)) {
02121     for (PRUint32 i = 0; i < num; i++)
02122       migrateAddressBookPrefEnum(arr[i]);
02123 
02124     NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(num, arr);
02125   }
02126 
02127   return rv;
02128 }
02129 
02130 #ifdef USE_NEWSRC_MAP_FILE
02131 #define NEWSRC_MAP_FILE_COOKIE "netscape-newsrc-map-file"
02132 #endif /* USE_NEWSRC_MAP_FILE */
02133 
02134 nsresult
02135 nsMessengerMigrator::MigrateNewsAccounts(nsIMsgIdentity *identity)
02136 {
02137     nsresult rv;
02138     nsCOMPtr <nsIFile> newsDir;
02139     nsFileSpec newsrcDir; // the directory that holds the newsrc files (and the fat file, if we are using one)
02140     nsFileSpec newsHostsDir; // the directory that holds the host directory, and the summary files.
02141     // the host directories will be under <profile dir>/News or
02142     // <"news.directory" pref>/News.
02143     //
02144     // the newsrc file don't necessarily live under there.
02145     //
02146     // if we didn't use the map file (UNIX) then we want to force the newsHostsDir to be
02147     // <profile>/News.  in 4.x, on UNIX, the summary files lived in ~/.netscape/xover-cache/<hostname>
02148     // in 5.0, they will live under <profile>/News/<hostname>, like the other platforms.
02149     // in 4.x, on UNIX, the "news.directory" pref pointed to the directory to where
02150     // the newsrc files lived.  we don't want that for the newsHostsDir.
02151 #ifdef USE_NEWSRC_MAP_FILE
02152     // if they used -installer, this pref will point to where their files got copied
02153     nsCOMPtr<nsILocalFile> localFile;
02154     rv = m_prefs->GetComplexValue(PREF_NEWS_DIRECTORY, NS_GET_IID(nsILocalFile), getter_AddRefs(localFile));
02155     if (NS_SUCCEEDED(rv))
02156         newsDir = localFile;
02157 #else
02158     rv = NS_ERROR_FAILURE;
02159 #endif /* USE_NEWSRC_MAP_FILE */
02160 
02161     if (!newsDir) {      
02162            rv = NS_GetSpecialDirectory(NS_APP_NEWS_50_DIR, getter_AddRefs(newsDir));
02163            if (NS_FAILED(rv)) return rv;
02164     }
02165  
02166     PRBool dirExists;
02167     rv = newsDir->Exists(&dirExists);
02168     if (NS_SUCCEEDED(rv) && !dirExists)
02169            newsDir->Create(nsIFile::DIRECTORY_TYPE, 0775);
02170     if (NS_FAILED(rv)) return rv;
02171     
02172     // TODO: convert users os nsIFileSpec to nsILocalFile
02173     // and avoid this step.
02174     nsCAutoString pathBuf;
02175     rv = newsDir->GetNativePath(pathBuf);
02176     if (NS_FAILED(rv)) return rv;
02177     newsHostsDir = pathBuf.get();    
02178     
02179 #ifdef USE_NEWSRC_MAP_FILE  
02180     // if we are using the fat file, it lives in the newsHostsDir.
02181     newsrcDir = newsHostsDir;
02182 
02183     // the fat file is really <newsrcDir>/<fat file name>
02184     // example:  News\fat on Windows, News\NewsFAT on the Mac
02185     // don't worry, after we migrate, the fat file is going away
02186     nsFileSpec fatFile(newsrcDir);
02187        fatFile += NEWS_FAT_FILE_NAME;
02188 
02189     // for each news server in the fat file call MigrateNewsAccount();
02190        char buffer[512];
02191        char psuedo_name[512];
02192        char filename[512];
02193        char is_newsgroup[512];
02194        PRBool ok;
02195 
02196        // check if the fat file exists
02197        // if not, return and handle it gracefully
02198        if (!fatFile.Exists()) {
02199               return NS_OK;
02200        }
02201 
02202        nsInputFileStream inputStream(fatFile);
02203        
02204        // if it exists, but it is empty, just return and handle it gracefully
02205        if (inputStream.eof()) {
02206               inputStream.close();
02207               return NS_OK;
02208        }
02209        
02210     /* we expect the first line to be NEWSRC_MAP_FILE_COOKIE */
02211        ok = inputStream.readline(buffer, sizeof(buffer));
02212        
02213     if ((!ok) || (PL_strncmp(buffer, NEWSRC_MAP_FILE_COOKIE, PL_strlen(NEWSRC_MAP_FILE_COOKIE)))) {
02214               inputStream.close();
02215               return NS_ERROR_FAILURE;
02216        }   
02217        
02218        while (!inputStream.eof()) {
02219               char * p;
02220               PRInt32 i;
02221               
02222               ok = inputStream.readline(buffer, sizeof(buffer));
02223               if (!ok) {
02224                      inputStream.close();
02225                      return NS_ERROR_FAILURE;
02226               }  
02227               
02228               /* TODO: replace this with nsString code? */
02229 
02230               /*
02231               This used to be scanf() call which would incorrectly
02232               parse long filenames with spaces in them.  - JRE
02233               */
02234               
02235               filename[0] = '\0';
02236               is_newsgroup[0]='\0';
02237               
02238               for (i = 0, p = buffer; *p && *p != '\t' && i < 500; p++, i++)
02239                      psuedo_name[i] = *p;
02240               psuedo_name[i] = '\0';
02241               if (*p) 
02242               {
02243                      for (i = 0, p++; *p && *p != '\t' && i < 500; p++, i++)
02244                             filename[i] = *p;
02245                      filename[i]='\0';
02246                      if (*p) 
02247                      {
02248                             for (i = 0, p++; *p && *p != '\r' && i < 500; p++, i++)
02249                                    is_newsgroup[i] = *p;
02250                             is_newsgroup[i]='\0';
02251                      }
02252               }
02253               
02254               if(PL_strncmp(is_newsgroup, "TRUE", 4)) {
02255 #ifdef NEWS_FAT_STORES_ABSOLUTE_NEWSRC_FILE_PATHS
02256                      // most likely, the fat file has been copied (or moved ) from
02257                      // its old location.  So the absolute file paths will be wrong.
02258                      // all we care about is the leaf, so use that.
02259                      nsFileSpec oldRcFile(filename);
02260                      char *leaf = oldRcFile.GetLeafName();
02261 
02262                      nsFileSpec rcFile(newsrcDir);
02263                      rcFile += leaf;
02264                      nsCRT::free(leaf);
02265                      leaf = nsnull;
02266 #else
02267                      nsFileSpec rcFile(newsrcDir);
02268                      rcFile += filename;
02269 #endif /* NEWS_FAT_STORES_ABSOLUTE_NEWSRC_FILE_PATHS */
02270 
02271                      // psuedo-name is of the form newsrc-<host> or snewsrc-<host>.  
02272                      if (PL_strncmp(PSUEDO_NAME_PREFIX,psuedo_name,PL_strlen(PSUEDO_NAME_PREFIX)) == 0) {
02273                 // check that there is a hostname to get after the "newsrc-" part
02274                 NS_ASSERTION(PL_strlen(psuedo_name) > PL_strlen(PSUEDO_NAME_PREFIX), "psuedo_name is too short");
02275                 if (PL_strlen(psuedo_name) <= PL_strlen(PSUEDO_NAME_PREFIX)) {
02276                     return NS_ERROR_FAILURE;
02277                 }
02278 
02279                 char *hostname = psuedo_name + PL_strlen(PSUEDO_NAME_PREFIX);
02280                 rv = MigrateNewsAccount(identity, hostname, rcFile, newsHostsDir, PR_FALSE /* isSecure */);
02281                 if (NS_FAILED(rv)) {
02282                     // failed to migrate.  bail out
02283                     return rv;
02284                 }
02285                      }
02286             else if (PL_strncmp(PSUEDO_SECURE_NAME_PREFIX,psuedo_name,PL_strlen(PSUEDO_SECURE_NAME_PREFIX)) == 0) {
02287                 // check that there is a hostname to get after the "snewsrc-" part
02288                 NS_ASSERTION(PL_strlen(psuedo_name) > PL_strlen(PSUEDO_SECURE_NAME_PREFIX), "psuedo_name is too short");
02289                 if (PL_strlen(psuedo_name) <= PL_strlen(PSUEDO_SECURE_NAME_PREFIX)) {
02290                     return NS_ERROR_FAILURE;
02291                 }
02292 
02293                 char *hostname = psuedo_name + PL_strlen(PSUEDO_SECURE_NAME_PREFIX);
02294                 rv = MigrateNewsAccount(identity, hostname, rcFile, newsHostsDir, PR_TRUE /* isSecure */);
02295                 if (NS_FAILED(rv)) {
02296                     // failed to migrate.  bail out
02297                     return rv;
02298                 }
02299             }
02300             else {
02301                 continue;
02302             }
02303               }
02304        }
02305        
02306        inputStream.close();
02307 #else /* USE_NEWSRC_MAP_FILE */
02308     nsCOMPtr<nsILocalFile> prefLocal;
02309     rv = m_prefs->GetComplexValue(PREF_NEWS_DIRECTORY, NS_GET_IID(nsILocalFile), getter_AddRefs(prefLocal));
02310     if (NS_FAILED(rv)) return rv;
02311     newsDir = prefLocal;
02312     
02313     {
02314         nsCAutoString pathBuf;
02315         newsDir->GetNativePath(pathBuf);
02316         if (NS_FAILED(rv)) return rv;
02317         newsrcDir = pathBuf.get();
02318     }
02319 
02320     for (nsDirectoryIterator i(newsrcDir, PR_FALSE); i.Exists(); i++) {
02321       nsFileSpec possibleRcFile = i.Spec();
02322 
02323       char *filename = possibleRcFile.GetLeafName();
02324       
02325       if ((PL_strncmp(NEWSRC_FILE_PREFIX_IN_5x, filename, PL_strlen(NEWSRC_FILE_PREFIX_IN_5x)) == 0) && (PL_strlen(filename) > PL_strlen(NEWSRC_FILE_PREFIX_IN_5x))) {
02326 #ifdef DEBUG_MIGRATOR
02327         printf("found a newsrc file: %s\n", filename);
02328 #endif
02329         char *hostname = filename + PL_strlen(NEWSRC_FILE_PREFIX_IN_5x);
02330         rv = MigrateNewsAccount(identity, hostname, possibleRcFile, newsHostsDir, PR_FALSE /* isSecure */);
02331         if (NS_FAILED(rv)) {
02332           // failed to migrate.  bail out
02333           nsCRT::free(filename);
02334           return rv;
02335         }
02336       }
02337       else if ((PL_strncmp(SNEWSRC_FILE_PREFIX_IN_5x, filename, PL_strlen(SNEWSRC_FILE_PREFIX_IN_5x)) == 0) && (PL_strlen(filename) > PL_strlen(SNEWSRC_FILE_PREFIX_IN_5x))) {
02338 #ifdef DEBUG_MIGRATOR
02339         printf("found a secure newsrc file: %s\n", filename);
02340 #endif
02341         char *hostname = filename + PL_strlen(SNEWSRC_FILE_PREFIX_IN_5x);
02342         rv = MigrateNewsAccount(identity, hostname, possibleRcFile, newsHostsDir, PR_TRUE /* isSecure */);
02343         if (NS_FAILED(rv)) {
02344           // failed to migrate.  bail out
02345           nsCRT::free(filename);
02346           return rv;
02347         }
02348       }
02349       nsCRT::free(filename);
02350       filename = nsnull;
02351     }
02352 #endif /* USE_NEWSRC_MAP_FILE */
02353 
02354        return NS_OK;
02355 }
02356 
02357 nsresult
02358 nsMessengerMigrator::MigrateNewsAccount(nsIMsgIdentity *identity, const char *hostAndPort, nsFileSpec & newsrcfile, nsFileSpec & newsHostsDir, PRBool isSecure)
02359 {  
02360        nsresult rv;
02361     nsCOMPtr<nsIMsgAccountManager> accountManager = 
02362              do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
02363     if (NS_FAILED(rv)) return rv;
02364 
02365        nsFileSpec thisNewsHostsDir = newsHostsDir;
02366     if (!identity) return NS_ERROR_NULL_POINTER;
02367        if (!hostAndPort) return NS_ERROR_NULL_POINTER;
02368 
02369     PRInt32 port=-1;
02370        nsCAutoString hostname(hostAndPort);
02371        PRInt32 colonPos = hostname.FindChar(':');
02372        if (colonPos != -1) {
02373               nsCAutoString portStr(hostAndPort + colonPos);
02374               hostname.Truncate(colonPos);
02375               PRInt32 err;
02376               port = portStr.ToInteger(&err);
02377               NS_ASSERTION(err == 0, "failed to get the port\n");
02378         if (err != 0)
02379           port=-1;
02380        }
02381 
02382     // create the server
02383        nsCOMPtr<nsIMsgIncomingServer> server;
02384     // for news, username is always null
02385     rv = accountManager->CreateIncomingServer(nsnull /* username */, hostname.get(), "nntp",
02386                               getter_AddRefs(server));
02387     NS_ENSURE_SUCCESS(rv,rv);
02388  
02389     if (port > 0) {
02390         rv = server->SetPort(port);
02391         NS_ENSURE_SUCCESS(rv,rv);
02392     }
02393     else {
02394         if (isSecure) {
02395             nsCOMPtr <nsIMsgProtocolInfo> protocolInfo = do_GetService("@mozilla.org/messenger/protocol/info;1?type=nntp", &rv);
02396             NS_ENSURE_SUCCESS(rv,rv);
02397     
02398             rv = protocolInfo->GetDefaultServerPort(PR_TRUE, &port);
02399             NS_ENSURE_SUCCESS(rv,rv);
02400 
02401             rv = server->SetPort(port);
02402             NS_ENSURE_SUCCESS(rv,rv);
02403         }
02404     }
02405 
02406     rv = server->SetIsSecure(isSecure);
02407     NS_ENSURE_SUCCESS(rv,rv);
02408 
02409 #ifdef DEBUG_MIGRATOR
02410        PRInt32 portValue;
02411        rv = server->GetPort(&portValue);
02412        printf("HOSTNAME = %s\n", hostname.get());
02413        printf("PORT = %d\n", portValue);
02414 #endif /* DEBUG_MIGRATOR */
02415 
02416     // we only need to do this once
02417     if (!m_alreadySetNntpDefaultLocalPath) {
02418       nsCOMPtr <nsIFileSpec>nntpRootDir;
02419       rv = NS_NewFileSpecWithSpec(newsHostsDir, getter_AddRefs(nntpRootDir));
02420       if (NS_FAILED(rv)) return rv;
02421       
02422       // set the default local path for "nntp"
02423       rv = server->SetDefaultLocalPath(nntpRootDir);
02424       if (NS_FAILED(rv)) return rv;
02425 
02426       // set the newsrc root for "nntp"
02427       // we really want <profile>/News or /home/sspitzer/
02428       // not <profile>/News/news.rc or /home/sspitzer/.newsrc-news
02429       nsFileSpec newsrcFileDir;
02430       newsrcfile.GetParent(newsrcFileDir);
02431       if (NS_FAILED(rv)) return rv;
02432       
02433       nsCOMPtr <nsIFileSpec>newsrcRootDir;
02434       rv = NS_NewFileSpecWithSpec(newsrcFileDir, getter_AddRefs(newsrcRootDir));
02435       if (NS_FAILED(rv)) return rv;
02436             
02437       nsCOMPtr<nsINntpIncomingServer> nntpServer;
02438       nntpServer = do_QueryInterface(server, &rv);
02439       if (NS_FAILED(rv)) return rv;
02440       rv = nntpServer->SetNewsrcRootPath(newsrcRootDir);
02441       if (NS_FAILED(rv)) return rv;
02442 
02443       m_alreadySetNntpDefaultLocalPath = PR_TRUE;
02444     }
02445     
02446 #ifdef DEBUG_MIGRATOR
02447     printf("migrate old nntp prefs\n");
02448 #endif /* DEBUG_MIGRATOR */
02449 
02450     rv = MigrateOldNntpPrefs(server, hostAndPort, newsrcfile);
02451     if (NS_FAILED(rv)) return rv;
02452               
02453        // can't do dir += "host-"; dir += hostname; 
02454        // because += on a nsFileSpec inserts a separator
02455        // so we'd end up with host-/<hostname> and not host-<hostname>
02456        nsCAutoString alteredHost;
02457     if (isSecure) {
02458         alteredHost = "shost-";
02459     }
02460     else {
02461         alteredHost = "host-";
02462     }
02463 
02464     // XXX hostname is assumed to be ASCII only here. To support IDN,
02465     // we have to use PRUnichar-version of NS_MsgHashIfNecessary
02466     // (ref. bug 264071)
02467        alteredHost += hostAndPort;
02468        NS_MsgHashIfNecessary(alteredHost);       
02469        thisNewsHostsDir += alteredHost.get();
02470 
02471     nsCOMPtr <nsIFileSpec> newsDir;
02472     PRBool dirExists;
02473        rv = NS_NewFileSpecWithSpec(thisNewsHostsDir, getter_AddRefs(newsDir));
02474        if (NS_FAILED(rv)) return rv;
02475 
02476 #ifdef DEBUG_MIGRATOR
02477     nsXPIDLCString nativePathStr;
02478     rv = newsDir->GetUnixStyleFilePath(getter_Copies(nativePathStr));
02479     if (NS_FAILED(rv)) return rv;
02480 
02481     printf("set the local path for this nntp server to: %s\n",(const char *)nativePathStr);
02482 #endif 
02483     rv = server->SetLocalPath(newsDir);
02484     if (NS_FAILED(rv)) return rv;
02485     
02486        rv = newsDir->Exists(&dirExists);
02487        if (!dirExists) {
02488               newsDir->CreateDir();
02489        }
02490 
02491   // create the identity
02492   nsCOMPtr<nsIMsgIdentity> copied_identity;
02493   rv = accountManager->CreateIdentity(getter_AddRefs(copied_identity));
02494   if (NS_FAILED(rv)) return rv;
02495 
02496   // Create an account when valid server and identity values are established.
02497   // This will keep the status of accounts sane by avoiding the addition of incomplete accounts. 
02498   nsCOMPtr<nsIMsgAccount> account;
02499   rv = accountManager->CreateAccount(getter_AddRefs(account));
02500   if (NS_FAILED(rv)) return rv;
02501 
02502   // hook the server to the account 
02503   // before setting the copies and folder prefs
02504   // (see bug #31904)
02505   // but after we set the server's local path
02506   // (see bug #66018)
02507   account->SetIncomingServer(server);
02508   account->AddIdentity(copied_identity);
02509 
02510   // make this new identity a copy of the identity
02511   // that we created out of the 4.x prefs
02512   rv = copied_identity->Copy(identity);
02513   if (NS_FAILED(rv)) return rv;
02514 
02515   rv = SetNewsCopiesAndFolders(copied_identity);
02516   if (NS_FAILED(rv)) return rv;
02517 
02518        return NS_OK;
02519 }
02520 
02521 nsresult
02522 nsMessengerMigrator::MigrateOldNntpPrefs(nsIMsgIncomingServer *server, const char *hostAndPort, nsFileSpec & newsrcfile)
02523 {
02524   nsresult rv;
02525   
02526   // some of this ought to be moved out into the NNTP implementation
02527   nsCOMPtr<nsINntpIncomingServer> nntpServer;
02528   nntpServer = do_QueryInterface(server, &rv);
02529   if (NS_FAILED(rv)) return rv;
02530 
02531   MIGRATE_SIMPLE_BOOL_PREF(PREF_4X_NEWS_NOTIFY_ON,nntpServer,SetNotifyOn)
02532   MIGRATE_SIMPLE_BOOL_PREF(PREF_4X_NEWS_MARK_OLD_READ,nntpServer,SetMarkOldRead)
02533   MIGRATE_SIMPLE_INT_PREF(PREF_4X_NEWS_MAX_ARTICLES,nntpServer,SetMaxArticles)
02534  
02535   /* in 4.x, news username and passwords did not persist beyond the session
02536    * so we don't need to call server->SetRememberPassword(PR_FALSE);
02537    * doing so is also bad since it will call nsNntpIncomingServer::ForgetPassword()
02538    * which fail since don't have any subfolders (newgroups) yet. 
02539    */
02540 
02541        
02542   nsCOMPtr <nsIFileSpec> path;
02543   rv = NS_NewFileSpecWithSpec(newsrcfile, getter_AddRefs(path));
02544   if (NS_FAILED(rv)) return rv;
02545 
02546   nntpServer->SetNewsrcFilePath(path);
02547     
02548   return NS_OK;
02549 }