Back to index

lightning-sunbird  0.9+nobinonly
nsEudoraWin32.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org Code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Pierre Phaneuf <pp@ludusdesign.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 "nsCOMPtr.h"
00041 #include "nsReadableUtils.h"
00042 #include "nsIComponentManager.h"
00043 #include "nsIServiceManager.h"
00044 #include "nsIMsgAccountManager.h"
00045 #include "nsIMsgAccount.h"
00046 #include "nsIPop3IncomingServer.h"
00047 #include "nsMsgBaseCID.h"
00048 #include "nsMsgCompCID.h"
00049 #include "nsISmtpService.h"
00050 #include "nsISmtpServer.h"
00051 #include "nsEudoraWin32.h"
00052 #include "nsIImportService.h"
00053 #include "nsIImportMailboxDescriptor.h"
00054 #include "nsIImportABDescriptor.h"
00055 #include "nsEudoraStringBundle.h"
00056 #include "nsEudoraImport.h"
00057 #include "nsUnicharUtils.h"
00058 #include "EudoraDebugLog.h"
00059 
00060 static NS_DEFINE_IID(kISupportsIID,                     NS_ISUPPORTS_IID);
00061 
00062 static const char *  kWhitespace = "\b\t\r\n ";
00063 
00064 // ::RegOpenKeyEx( HKEY_CURRENT_USER, "Software\\Accounts", 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &sKey) == ERROR_SUCCESS)
00065 
00066 BYTE * nsEudoraWin32::GetValueBytes( HKEY hKey, const char *pValueName)
00067 {
00068        LONG   err;
00069        DWORD  bufSz;
00070        LPBYTE pBytes = NULL;
00071 
00072        err = ::RegQueryValueEx( hKey, pValueName, NULL, NULL, NULL, &bufSz); 
00073        if (err == ERROR_SUCCESS) {
00074               pBytes = new BYTE[bufSz];
00075               err = ::RegQueryValueEx( hKey, pValueName, NULL, NULL, pBytes, &bufSz);
00076               if (err != ERROR_SUCCESS) {
00077                      delete [] pBytes;
00078                      pBytes = NULL;
00079               }
00080        }
00081 
00082        return( pBytes);
00083 }
00084 
00085 
00086 nsEudoraWin32::nsEudoraWin32()
00087 {
00088        m_mailImportLocation = nsnull;
00089        m_addressImportFolder = nsnull;
00090        m_pMimeSection = nsnull;
00091 }
00092 
00093 nsEudoraWin32::~nsEudoraWin32()
00094 {
00095        NS_IF_RELEASE( m_mailImportLocation);
00096        NS_IF_RELEASE( m_addressImportFolder);
00097        if (m_pMimeSection)
00098               delete [] m_pMimeSection;
00099 }
00100 
00101 PRBool nsEudoraWin32::FindMailFolder( nsIFileSpec *pFolder)
00102 {
00103        return( FindEudoraLocation( pFolder));
00104 }
00105 
00106 PRBool nsEudoraWin32::FindEudoraLocation( nsIFileSpec *pFolder, PRBool findIni)
00107 {
00108        PRBool result = PR_FALSE;
00109   PRBool  exists = PR_FALSE;
00110 
00111        // look in the registry to see where eudora is installed?
00112        HKEY   sKey;
00113        if (::RegOpenKeyEx( HKEY_CURRENT_USER, "Software\\Qualcomm\\Eudora\\CommandLine", 0, KEY_QUERY_VALUE, &sKey) == ERROR_SUCCESS) {
00114               // get the value of "Current"
00115               BYTE *pBytes = GetValueBytes( sKey, "Current");
00116               if (pBytes) {
00117                      nsCString str((const char *)pBytes);
00118                      delete [] pBytes;
00119                      
00120       str.CompressWhitespace();
00121                      
00122                      // Command line is Eudora mailfolder eudora.ini
00123       if (findIni) {
00124         // find the string coming after the last space
00125         PRInt32 index = str.RFind(" ");
00126         if (index != -1) {
00127           index++; // skip the space
00128           nsCString  path;
00129                                    str.Mid( path, index, str.Length() - index);
00130 
00131           pFolder->SetNativePath( path.get());
00132           pFolder->IsFile( &exists);
00133           if (exists)
00134                                      result = exists;
00135           else // it may just be the mailbox location....guess that there will be a eudora.ini file there
00136           {
00137             pFolder->AppendRelativeUnixPath("eudora.ini");
00138             pFolder->IsFile( &exists);
00139                                      result = exists;
00140           }       
00141         } 
00142       } // if findIni
00143       else {
00144                      int    idx = -1;
00145                      if (str.CharAt( 0) == '"') {
00146                             idx = str.FindChar( '"', 1);
00147                             if (idx != -1)
00148                                    idx++;
00149                      }
00150                      else {
00151                             idx = str.FindChar( ' ');
00152                      }
00153                      
00154                      if (idx != -1) {
00155                             idx++;
00156                             while (str.CharAt( idx) == ' ') idx++;
00157                             int endIdx = -1;
00158                             if (str.CharAt( idx) == '"') {
00159                                    endIdx = str.FindChar( '"', idx);
00160                             }
00161                             else {
00162                                    endIdx = str.FindChar( ' ', idx);
00163                             }
00164                             if (endIdx != -1) {
00165                                    nsCString     path;
00166                                    str.Mid( path, idx, endIdx - idx);                             
00167                                    
00168                                    pFolder->SetNativePath( path.get());
00169 
00170                                      if (NS_SUCCEEDED( pFolder->IsDirectory( &exists)))
00171                                                  result = exists;
00172                                           }
00173                                    }
00174                             }
00175     } // if pBytes
00176               ::RegCloseKey( sKey);
00177        }
00178 
00179        return( result);
00180 }
00181 
00182 nsresult nsEudoraWin32::FindMailboxes( nsIFileSpec *pRoot, nsISupportsArray **ppArray)
00183 {
00184        nsresult rv = NS_NewISupportsArray( ppArray);
00185        if (NS_FAILED( rv)) {
00186               IMPORT_LOG0( "FAILED to allocate the nsISupportsArray\n");
00187               return( rv);
00188        }
00189               
00190        nsCOMPtr<nsIImportService> impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
00191        if (NS_FAILED( rv))
00192               return( rv);
00193        
00194        m_depth = 0;
00195        NS_IF_RELEASE( m_mailImportLocation);
00196        m_mailImportLocation = pRoot;
00197        NS_IF_ADDREF( m_mailImportLocation);
00198 
00199        return( ScanMailDir( pRoot, *ppArray, impSvc));
00200 }
00201 
00202 
00203 nsresult nsEudoraWin32::ScanMailDir( nsIFileSpec *pFolder, nsISupportsArray *pArray, nsIImportService *pImport)
00204 {
00205        PRBool                             exists = PR_FALSE;
00206        PRBool                             isFile = PR_FALSE;
00207        char *                             pContents = nsnull;
00208        PRInt32                                   len = 0;
00209        nsCOMPtr<nsIFileSpec>       descMap;
00210        nsresult                           rv;
00211 
00212        if (NS_FAILED( rv = NS_NewFileSpec( getter_AddRefs( descMap))))
00213               return( rv);
00214 
00215        m_depth++;
00216 
00217        descMap->FromFileSpec( pFolder);
00218        rv = descMap->AppendRelativeUnixPath( "descmap.pce");
00219        if (NS_SUCCEEDED( rv))
00220               rv = descMap->IsFile( &isFile);
00221        if (NS_SUCCEEDED( rv))
00222               rv = descMap->Exists( &exists);
00223        if (NS_SUCCEEDED( rv) && exists && isFile) {
00224               rv = descMap->GetFileContents( &pContents);
00225               if (NS_SUCCEEDED( rv) && pContents) {
00226                      len = strlen( pContents);   
00227                      if (NS_SUCCEEDED( rv))
00228                             rv = ScanDescmap( pFolder, pArray, pImport, pContents, len);
00229                      nsCRT::free( pContents);
00230               }
00231               else
00232                      rv = NS_ERROR_FAILURE;
00233        }
00234 
00235        if (NS_FAILED( rv) || !isFile || !exists)
00236               rv = IterateMailDir( pFolder, pArray, pImport);
00237        
00238        m_depth--;
00239 
00240        return( rv);                
00241 }
00242 
00243 nsresult nsEudoraWin32::IterateMailDir( nsIFileSpec *pFolder, nsISupportsArray *pArray, nsIImportService *pImport)
00244 {
00245        nsCOMPtr<nsIDirectoryIterator>     dir;
00246        nsresult rv = NS_NewDirectoryIterator( getter_AddRefs( dir));
00247        if (NS_FAILED( rv))
00248               return( rv);
00249 
00250        PRBool exists = PR_FALSE;
00251        rv = dir->Init( pFolder, PR_TRUE);
00252        if (NS_FAILED( rv))
00253               return( rv);
00254 
00255        rv = dir->Exists( &exists);
00256        if (NS_FAILED( rv))
00257               return( rv);
00258        
00259        PRBool                             isFolder;
00260        PRBool                             isFile;
00261        nsCOMPtr<nsIFileSpec>       entry;
00262        char *                             pName;
00263        nsCString                          fName;
00264        nsCString                          ext;
00265        nsCString                          name;
00266 
00267        while (exists && NS_SUCCEEDED( rv)) {
00268               rv = dir->GetCurrentSpec( getter_AddRefs( entry));
00269               if (NS_SUCCEEDED( rv)) {
00270                      rv = entry->GetLeafName( &pName);
00271                      if (NS_SUCCEEDED( rv) && pName) {
00272                             fName = pName;
00273                             nsCRT::free( pName);
00274                             if (fName.Length() > 4) {
00275                                    fName.Right( ext, 4);
00276                                    fName.Left( name, fName.Length() - 4);
00277                             }
00278                             else {
00279                                    ext.Truncate();
00280                                    name = fName;
00281                             }
00282                             ToLowerCase(ext);
00283                             if (ext.EqualsLiteral(".fol")) {
00284                                    isFolder = PR_FALSE;
00285                                    entry->IsDirectory( &isFolder);
00286                                    if (isFolder) {
00287                                           // add the folder
00288                                           rv = FoundMailFolder( entry, name.get(), pArray, pImport);
00289                                           if (NS_SUCCEEDED( rv)) {
00290                                                  rv = ScanMailDir( entry, pArray, pImport);
00291                                                  if (NS_FAILED( rv)) {
00292                                                         IMPORT_LOG0( "*** Error scanning mail directory\n");
00293                                                  }
00294                                           }
00295                                    }
00296                             }
00297                             else if (ext.EqualsLiteral(".mbx")) {
00298                                    isFile = PR_FALSE;
00299                                    entry->IsFile( &isFile);
00300                                    if (isFile) {
00301                                           rv = FoundMailbox( entry, name.get(), pArray, pImport);
00302                                    }
00303                             }
00304                      }                           
00305               }
00306 
00307               rv = dir->Next();
00308               if (NS_SUCCEEDED( rv))
00309                      rv = dir->Exists( &exists);
00310        }
00311 
00312        return( rv);
00313 }
00314 
00315 nsresult nsEudoraWin32::ScanDescmap( nsIFileSpec *pFolder, nsISupportsArray *pArray, nsIImportService *pImport, const char *pData, PRInt32 len)
00316 {
00317        // use this to find stuff in the directory.
00318 
00319        nsCOMPtr<nsIFileSpec>       entry;
00320        nsresult                           rv;
00321 
00322        if (NS_FAILED( rv = NS_NewFileSpec( getter_AddRefs( entry))))
00323               return( rv);
00324        
00325        // format is Name,FileName,Type,Flag?
00326        //     Type = M or S for mailbox
00327        //             = F for folder
00328 
00329        PRInt32                     fieldLen;
00330        PRInt32                     pos = 0;
00331        const char *  pStart;
00332        nsCString            name;
00333        nsCString            fName;
00334        nsCString            type;
00335        nsCString            flag;
00336        PRBool               isFile;
00337        PRBool               isFolder;
00338        while (pos < len) {
00339               pStart = pData;
00340               fieldLen = 0;
00341               while ((pos < len) && (*pData != ',')) {
00342                      pos++;
00343                      pData++;
00344                      fieldLen++;
00345               }
00346               name.Truncate();
00347               if (fieldLen)
00348                      name.Append( pStart, fieldLen);
00349               name.Trim( kWhitespace);
00350               pos++;
00351               pData++;
00352               pStart = pData;
00353               fieldLen = 0;
00354               while ((pos < len) && (*pData != ',')) {
00355                      pos++;
00356                      pData++;
00357                      fieldLen++;
00358               }
00359               fName.Truncate();
00360               if (fieldLen)
00361                      fName.Append( pStart, fieldLen);
00362                 // Descmap file name is written without any extraneous white space - i.e.
00363                 // if there's whitespace present it's intentional and important. Don't
00364                 // strip whitespace from the fName.
00365               pos++;
00366               pData++;
00367               pStart = pData;
00368               fieldLen = 0;
00369               while ((pos < len) && (*pData != ',')) {
00370                      pos++;
00371                      pData++;
00372                      fieldLen++;
00373               }
00374               type.Truncate();
00375               if (fieldLen)
00376                      type.Append( pStart, fieldLen);           
00377               type.Trim( kWhitespace);
00378               pos++;
00379               pData++;
00380               pStart = pData;
00381               fieldLen = 0;
00382               while ((pos < len) && (*pData != 0x0D) && (*pData != 0x0A) && (*pData != ',')) {
00383                      pos++;
00384                      pData++;
00385                      fieldLen++;
00386               }
00387               flag.Truncate();
00388               if (fieldLen)
00389                      flag.Append( pStart, fieldLen);           
00390               flag.Trim( kWhitespace);
00391               while ((pos < len) && ((*pData == 0x0D) || (*pData == 0x0A))) {
00392                      pos++;
00393                      pData++;
00394               }
00395 
00396               IMPORT_LOG2( "name: %s, fName: %s\n", name.get(), fName.get());
00397 
00398               if (!fName.IsEmpty() && !name.IsEmpty() && (type.Length() == 1)) {
00399                      entry->FromFileSpec( pFolder);
00400                      rv = entry->AppendRelativeUnixPath( fName.get());
00401                      if (NS_SUCCEEDED( rv)) {
00402                             if (type.CharAt( 0) == 'F') {
00403                                    isFolder = PR_FALSE;
00404                                    entry->IsDirectory( &isFolder);
00405                                    if (isFolder) {
00406                                           rv = FoundMailFolder( entry, name.get(), pArray, pImport);
00407                                           if (NS_SUCCEEDED( rv)) {
00408                                                  rv = ScanMailDir( entry, pArray, pImport);
00409                                                  if (NS_FAILED( rv)) {
00410                                                         IMPORT_LOG0( "*** Error scanning mail directory\n");
00411                                                  }
00412                                           }
00413                                    }
00414                             }
00415                             else if ((type.CharAt( 0) == 'M') || (type.CharAt( 0) == 'S')) {
00416                                    isFile = PR_FALSE;
00417                                    entry->IsFile( &isFile);
00418                                    if (isFile) {
00419                                           FoundMailbox( entry, name.get(), pArray, pImport);
00420                                    }
00421                             }
00422                      }
00423               }
00424        }
00425 
00426        return( NS_OK);
00427 }
00428 
00429 
00430 nsresult nsEudoraWin32::FoundMailbox( nsIFileSpec *mailFile, const char *pName, nsISupportsArray *pArray, nsIImportService *pImport)
00431 {
00432        nsString                                                       displayName;
00433        nsCOMPtr<nsIImportMailboxDescriptor>      desc;
00434        nsISupports *                                           pInterface;
00435 
00436        NS_CopyNativeToUnicode(nsDependentCString(pName), displayName);
00437 
00438 #ifdef IMPORT_DEBUG
00439        char *pPath = nsnull;
00440        mailFile->GetNativePath( &pPath);
00441        if (pPath) {
00442               IMPORT_LOG2( "Found eudora mailbox, %s: %s\n", pPath, pName);
00443               nsCRT::free( pPath);
00444        }
00445        else {
00446               IMPORT_LOG1( "Found eudora mailbox, %s\n", pName);
00447        }
00448        IMPORT_LOG1( "\tm_depth = %d\n", (int)m_depth);
00449 #endif
00450 
00451        nsresult rv = pImport->CreateNewMailboxDescriptor( getter_AddRefs( desc));
00452        if (NS_SUCCEEDED( rv)) {
00453               PRUint32             sz = 0;
00454               mailFile->GetFileSize( &sz);       
00455               desc->SetDisplayName( displayName.get());
00456               desc->SetDepth( m_depth);
00457               desc->SetSize( sz);
00458               nsIFileSpec *pSpec = nsnull;
00459               desc->GetFileSpec( &pSpec);
00460               if (pSpec) {
00461                      pSpec->FromFileSpec( mailFile);
00462                      NS_RELEASE( pSpec);
00463               }
00464               rv = desc->QueryInterface( kISupportsIID, (void **) &pInterface);
00465               pArray->AppendElement( pInterface);
00466               pInterface->Release();
00467        }
00468 
00469        return( NS_OK);
00470 }
00471 
00472 
00473 nsresult nsEudoraWin32::FoundMailFolder( nsIFileSpec *mailFolder, const char *pName, nsISupportsArray *pArray, nsIImportService *pImport)
00474 {
00475        nsString                                                       displayName;
00476        nsCOMPtr<nsIImportMailboxDescriptor>      desc;
00477        nsISupports *                                           pInterface;
00478 
00479        NS_CopyNativeToUnicode(nsDependentCString(pName), displayName);
00480 
00481 #ifdef IMPORT_DEBUG
00482        char *pPath = nsnull;
00483        mailFolder->GetNativePath( &pPath);
00484        if (pPath) {
00485               IMPORT_LOG2( "Found eudora folder, %s: %s\n", pPath, pName);
00486               nsCRT::free( pPath);
00487        }
00488        else {
00489               IMPORT_LOG1( "Found eudora folder, %s\n", pName);
00490        }
00491        IMPORT_LOG1( "\tm_depth = %d\n", (int)m_depth);
00492 #endif
00493 
00494        nsresult rv = pImport->CreateNewMailboxDescriptor( getter_AddRefs( desc));
00495        if (NS_SUCCEEDED( rv)) {
00496               PRUint32             sz = 0;
00497               desc->SetDisplayName( displayName.get());
00498               desc->SetDepth( m_depth);
00499               desc->SetSize( sz);
00500               nsIFileSpec *pSpec = nsnull;
00501               desc->GetFileSpec( &pSpec);
00502               if (pSpec) {
00503                      pSpec->FromFileSpec( mailFolder);
00504                      NS_RELEASE( pSpec);
00505               }
00506               rv = desc->QueryInterface( kISupportsIID, (void **) &pInterface);
00507               pArray->AppendElement( pInterface);
00508               pInterface->Release();
00509        }
00510 
00511        return( NS_OK);
00512 }
00513 
00514 
00515 nsresult nsEudoraWin32::FindTOCFile( nsIFileSpec *pMailFile, nsIFileSpec **ppTOCFile, PRBool *pDeleteToc)
00516 {
00517        nsresult             rv;
00518        char   *             pName = nsnull;
00519 
00520        *pDeleteToc = PR_FALSE;
00521        *ppTOCFile = nsnull;
00522        rv = pMailFile->GetLeafName( &pName);
00523        if (NS_FAILED( rv))
00524               return( rv);
00525        rv = pMailFile->GetParent( ppTOCFile);
00526        if (NS_FAILED( rv))
00527               return( rv);
00528 
00529        nsCString     leaf(pName);
00530        nsCRT::free( pName);
00531        nsCString     name;
00532        if ((leaf.Length() > 4) && (leaf.CharAt( leaf.Length() - 4) == '.'))
00533               leaf.Left( name, leaf.Length() - 4);
00534        else
00535               name = leaf;
00536        name.Append( ".toc");
00537        rv = (*ppTOCFile)->AppendRelativeUnixPath( name.get());
00538        if (NS_FAILED( rv))
00539               return( rv);
00540 
00541        PRBool exists = PR_FALSE;
00542        rv = (*ppTOCFile)->Exists( &exists);
00543        if (NS_FAILED( rv))
00544               return( rv);
00545        PRBool isFile = PR_FALSE;
00546        rv = (*ppTOCFile)->IsFile( &isFile);
00547        if (NS_FAILED( rv))
00548               return( rv);
00549        if (exists && isFile)
00550               return( NS_OK);
00551               
00552        return( NS_ERROR_FAILURE);
00553 }
00554 
00555 
00556 PRBool nsEudoraWin32::ImportSettings( nsIFileSpec *pIniFile, nsIMsgAccount **localMailAccount)
00557 {
00558        PRBool        result = PR_FALSE;
00559        nsresult      rv;
00560 
00561        nsCOMPtr<nsIMsgAccountManager> accMgr = 
00562                 do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
00563     if (NS_FAILED(rv)) {
00564               IMPORT_LOG0( "*** Failed to create a account manager!\n");
00565               return( PR_FALSE);
00566        }
00567 
00568        // Eudora info is arranged by key, 1 for the default, then persona's for additional
00569        // accounts.
00570        // Start with the first one, then do each persona
00571        char *pIniPath = nsnull;
00572        pIniFile->GetNativePath( &pIniPath);
00573        if (!pIniPath)
00574               return( PR_FALSE);
00575 
00576        nsCString     iniPath(pIniPath);
00577        nsCRT::free( pIniPath);
00578        
00579        UINT                 valInt;
00580        SimpleBufferTonyRCopiedOnce section;
00581        DWORD                sSize;
00582        DWORD                sOffset = 0;
00583        DWORD                start;
00584        nsCString            sectionName("Settings");
00585        int                         popCount = 0;
00586        int                         accounts = 0;
00587        
00588        DWORD  allocSize = 0;
00589        do {
00590               allocSize += 2048;
00591               section.Allocate( allocSize);
00592               sSize = ::GetPrivateProfileSection( "Personalities", section.m_pBuffer, allocSize, iniPath.get());
00593        } while (sSize == (allocSize - 2));
00594        
00595        nsIMsgAccount *      pAccount;
00596 
00597        do {
00598               if (!sectionName.IsEmpty()) {
00599                      pAccount = nsnull;
00600                      valInt = ::GetPrivateProfileInt( sectionName.get(), "UsesPOP", 1, iniPath.get());
00601                      if (valInt) {
00602                             // This is a POP account
00603                             if (BuildPOPAccount( accMgr, sectionName.get(), iniPath.get(), &pAccount)) {
00604                                    accounts++;
00605                                    popCount++;
00606                                    if (popCount > 1) {
00607                                           if (localMailAccount && *localMailAccount) {
00608                                                  NS_RELEASE( *localMailAccount);
00609                                                  *localMailAccount = nsnull;
00610                                           }
00611                                    }
00612                                    else {
00613                                           if (localMailAccount) {
00614                                                  *localMailAccount = pAccount;
00615                                                  NS_IF_ADDREF( pAccount);
00616                                           }                                  
00617                                    }
00618                             }
00619                      }
00620                      else {
00621                             valInt = ::GetPrivateProfileInt( sectionName.get(), "UsesIMAP", 0, iniPath.get());
00622                             if (valInt) {
00623                                    // This is an IMAP account
00624                                    if (BuildIMAPAccount( accMgr, sectionName.get(), iniPath.get(), &pAccount)) {
00625                                           accounts++;
00626                                    }
00627                             }
00628                      }
00629                      if (pAccount && (sOffset == 0)) {
00630                             accMgr->SetDefaultAccount( pAccount);
00631                      }
00632 
00633                      NS_IF_RELEASE( pAccount);
00634               }
00635                             
00636               sectionName.Truncate();
00637               while ((sOffset < sSize) && (section.m_pBuffer[sOffset] != '='))
00638                      sOffset++;
00639               sOffset++;
00640               start = sOffset;
00641               while ((sOffset < sSize) && (section.m_pBuffer[sOffset] != 0))
00642                      sOffset++;
00643               if (sOffset > start) {
00644                      sectionName.Append( section.m_pBuffer + start, sOffset - start);
00645                      sectionName.Trim( kWhitespace);
00646               }
00647 
00648        } while (sOffset < sSize);
00649 
00650        // Now save the new acct info to pref file.
00651        rv = accMgr->SaveAccountInfo();
00652        NS_ASSERTION(NS_SUCCEEDED(rv), "Can't save account info to pref file");
00653 
00654 
00655        return( accounts != 0);
00656 }
00657 
00658 // maximium size of settings strings
00659 #define       kIniValueSize        384
00660 
00661 
00662 void nsEudoraWin32::GetServerAndUserName( const char *pSection, const char *pIni, nsCString& serverName, nsCString& userName, char *pBuff)
00663 {
00664        DWORD         valSize;
00665        int                  idx;
00666        nsCString     tStr;
00667 
00668        serverName.Truncate();
00669        userName.Truncate();
00670 
00671        valSize = ::GetPrivateProfileString( pSection, "PopServer", "", pBuff, kIniValueSize, pIni);
00672        if (valSize)
00673               serverName = pBuff;
00674        else {
00675               valSize = ::GetPrivateProfileString( pSection, "POPAccount", "", pBuff, kIniValueSize, pIni);
00676               if (valSize) {
00677                      serverName = pBuff;
00678                      idx = serverName.FindChar( '@');
00679                      if (idx != -1) {
00680                             serverName.Right( tStr, serverName.Length() - idx - 1);
00681                             serverName = tStr;
00682                      }
00683               }
00684        }
00685        valSize = ::GetPrivateProfileString( pSection, "LoginName", "", pBuff, kIniValueSize, pIni);
00686        if (valSize)
00687               userName = pBuff;
00688        else {
00689               valSize = ::GetPrivateProfileString( pSection, "POPAccount", "", pBuff, kIniValueSize, pIni);
00690               if (valSize) {
00691                      userName = pBuff;
00692                      idx = userName.FindChar( '@');
00693                      if (idx != -1) {
00694                             userName.Left( tStr, idx);
00695                             userName = tStr;
00696                      }
00697               }
00698        }
00699 }
00700 
00701 void nsEudoraWin32::GetAccountName( const char *pSection, nsString& str)
00702 {
00703        str.Truncate();
00704 
00705        nsCString     s(pSection);
00706        
00707        if (s.Equals(NS_LITERAL_CSTRING("Settings"), nsCaseInsensitiveCStringComparator())) {
00708               str.AssignLiteral("Eudora ");
00709               str.AppendWithConversion( pSection);
00710        }
00711        else {
00712               nsCString tStr;
00713               str.AssignWithConversion(pSection);
00714               if (s.Length() > 8) {
00715                      s.Left( tStr, 8); 
00716                      if (tStr.Equals(NS_LITERAL_CSTRING("Persona-"), nsCaseInsensitiveCStringComparator())) {
00717                             s.Right( tStr, s.Length() - 8);
00718                             str.AssignWithConversion(tStr.get());
00719                      }
00720               }
00721        }
00722 }
00723 
00724 
00725 PRBool nsEudoraWin32::BuildPOPAccount( nsIMsgAccountManager *accMgr, const char *pSection, const char *pIni, nsIMsgAccount **ppAccount)
00726 {
00727        if (ppAccount)
00728               *ppAccount = nsnull;
00729        
00730        char          valBuff[kIniValueSize];
00731        nsCString     serverName;
00732        nsCString     userName;
00733        
00734        GetServerAndUserName( pSection, pIni, serverName, userName, valBuff);
00735        
00736        if (serverName.IsEmpty() || userName.IsEmpty())
00737               return( PR_FALSE);
00738 
00739        PRBool result = PR_FALSE;
00740 
00741        // I now have a user name/server name pair, find out if it already exists?
00742        nsCOMPtr<nsIMsgIncomingServer>     in;
00743        nsresult rv = accMgr->FindServer( userName.get(), serverName.get(), "pop3", getter_AddRefs( in));
00744        if (NS_FAILED( rv) || (in == nsnull)) {
00745               // Create the incoming server and an account for it?
00746               rv = accMgr->CreateIncomingServer( userName.get(), serverName.get(), "pop3", getter_AddRefs( in));
00747               if (NS_SUCCEEDED( rv) && in) {
00748                      rv = in->SetType( "pop3");
00749                      // rv = in->SetHostName( serverName);
00750                      // rv = in->SetUsername( userName);
00751 
00752                      IMPORT_LOG2( "Created POP3 server named: %s, userName: %s\n", serverName.get(), userName.get());
00753 
00754                      nsString      prettyName;
00755                      GetAccountName( pSection, prettyName);
00756 
00757                      PRUnichar *pretty = ToNewUnicode(prettyName);
00758                      IMPORT_LOG1( "\tSet pretty name to: %S\n", pretty);
00759                      rv = in->SetPrettyName( pretty);
00760                      nsCRT::free( pretty);
00761                      
00762                      // We have a server, create an account.
00763                      nsCOMPtr<nsIMsgAccount>     account;
00764                      rv = accMgr->CreateAccount( getter_AddRefs( account));
00765                      if (NS_SUCCEEDED( rv) && account) {
00766                             rv = account->SetIncomingServer( in);
00767 
00768                             IMPORT_LOG0( "Created a new account and set the incoming server to the POP3 server.\n");
00769                                    
00770         nsCOMPtr<nsIPop3IncomingServer> pop3Server = do_QueryInterface(in, &rv);
00771         NS_ENSURE_SUCCESS(rv,rv);
00772         UINT valInt = ::GetPrivateProfileInt(pSection, "LeaveMailOnServer", 0, pIni);
00773         pop3Server->SetLeaveMessagesOnServer(valInt ? PR_TRUE : PR_FALSE);
00774                             
00775                             // Fiddle with the identities
00776                             SetIdentities(accMgr, account, pSection, pIni, userName.get(), serverName.get(), valBuff);
00777                             result = PR_TRUE;
00778                             if (ppAccount)
00779                                    account->QueryInterface( NS_GET_IID(nsIMsgAccount), (void **)ppAccount);
00780                      }                           
00781               }
00782        }
00783        else
00784               result = PR_TRUE;
00785        
00786        return( result);
00787 }
00788 
00789 
00790 PRBool nsEudoraWin32::BuildIMAPAccount( nsIMsgAccountManager *accMgr, const char *pSection, const char *pIni, nsIMsgAccount **ppAccount)
00791 {
00792        char          valBuff[kIniValueSize];
00793        nsCString     serverName;
00794        nsCString     userName;
00795        
00796        GetServerAndUserName( pSection, pIni, serverName, userName, valBuff);
00797        
00798        if (serverName.IsEmpty() || userName.IsEmpty())
00799               return( PR_FALSE);
00800 
00801        PRBool result = PR_FALSE;
00802 
00803        nsCOMPtr<nsIMsgIncomingServer>     in;
00804        nsresult rv = accMgr->FindServer( userName.get(), serverName.get(), "imap", getter_AddRefs( in));
00805        if (NS_FAILED( rv) || (in == nsnull)) {
00806               // Create the incoming server and an account for it?
00807               rv = accMgr->CreateIncomingServer( userName.get(), serverName.get(), "imap", getter_AddRefs( in));
00808               if (NS_SUCCEEDED( rv) && in) {
00809                      rv = in->SetType( "imap");
00810                      // rv = in->SetHostName( serverName);
00811                      // rv = in->SetUsername( userName);
00812                      
00813                      IMPORT_LOG2( "Created IMAP server named: %s, userName: %s\n", serverName.get(), userName.get());
00814                      
00815                      nsString      prettyName;
00816                      GetAccountName( pSection, prettyName);
00817 
00818                      PRUnichar *pretty = ToNewUnicode(prettyName);
00819                      
00820                      IMPORT_LOG1( "\tSet pretty name to: %S\n", pretty);
00821 
00822                      rv = in->SetPrettyName( pretty);
00823                      nsCRT::free( pretty);
00824                      
00825                      // We have a server, create an account.
00826                      nsCOMPtr<nsIMsgAccount>     account;
00827                      rv = accMgr->CreateAccount( getter_AddRefs( account));
00828                      if (NS_SUCCEEDED( rv) && account) {
00829                             rv = account->SetIncomingServer( in);     
00830                             
00831                             IMPORT_LOG0( "Created an account and set the IMAP server as the incoming server\n");
00832 
00833                             // Fiddle with the identities
00834                             SetIdentities(accMgr, account, pSection, pIni, userName.get(), serverName.get(), valBuff);
00835                             result = PR_TRUE;
00836                             if (ppAccount)
00837                                    account->QueryInterface( NS_GET_IID(nsIMsgAccount), (void **)ppAccount);
00838                      }                           
00839               }
00840        }
00841        else
00842               result = PR_TRUE;
00843 
00844        return( result);
00845 }
00846 
00847 void nsEudoraWin32::SetIdentities(nsIMsgAccountManager *accMgr, nsIMsgAccount *acc, const char *pSection, const char *pIniFile, const char *userName, const char *serverName, char *pBuff)
00848 {
00849        nsCAutoString realName;
00850        nsCAutoString email;
00851        nsCAutoString server;
00852        DWORD         valSize;
00853        nsresult      rv;
00854 
00855        valSize = ::GetPrivateProfileString( pSection, "RealName", "", pBuff, kIniValueSize, pIniFile);
00856        if (valSize)
00857               realName = pBuff;
00858        valSize = ::GetPrivateProfileString( pSection, "SMTPServer", "", pBuff, kIniValueSize, pIniFile);
00859        if (valSize)
00860               server = pBuff;
00861        valSize = ::GetPrivateProfileString( pSection, "ReturnAddress", "", pBuff, kIniValueSize, pIniFile);
00862        if (valSize)
00863               email = pBuff;
00864        
00865        nsCOMPtr<nsIMsgIdentity>    id;
00866        rv = accMgr->CreateIdentity( getter_AddRefs( id));
00867        if (id) {
00868               nsAutoString fullName; 
00869               fullName.AssignWithConversion(realName.get());
00870               id->SetFullName( fullName.get());
00871               id->SetIdentityName( fullName.get());
00872               if (email.IsEmpty()) {
00873                      email = userName;
00874                      email += "@";
00875                      email += serverName;
00876               }
00877               id->SetEmail(email.get());
00878               acc->AddIdentity( id);
00879 
00880               IMPORT_LOG0( "Created identity and added to the account\n");
00881               IMPORT_LOG1( "\tname: %s\n", realName.get());
00882               IMPORT_LOG1( "\temail: %s\n", email.get());
00883        }
00884 
00885        SetSmtpServer( accMgr, acc, server.get(), userName);
00886               
00887 }
00888 
00889 
00890 void nsEudoraWin32::SetSmtpServer( nsIMsgAccountManager *pMgr, nsIMsgAccount *pAcc, const char *pServer, const char *pUser)
00891 {
00892        nsresult      rv;
00893        
00894        nsCOMPtr<nsISmtpService> smtpService(do_GetService(NS_SMTPSERVICE_CONTRACTID, &rv)); 
00895        if (NS_SUCCEEDED(rv) && smtpService) {
00896               nsCOMPtr<nsISmtpServer>            foundServer;
00897        
00898               rv = smtpService->FindServer( pUser, pServer, getter_AddRefs( foundServer));
00899               if (NS_SUCCEEDED( rv) && foundServer) {
00900                      IMPORT_LOG1( "SMTP server already exists: %s\n", pServer);
00901                      return;
00902               }
00903               nsCOMPtr<nsISmtpServer>            smtpServer;
00904               
00905               rv = smtpService->CreateSmtpServer( getter_AddRefs( smtpServer));
00906               if (NS_SUCCEEDED( rv) && smtpServer) {
00907                      smtpServer->SetHostname( pServer);
00908                      if (pUser)
00909                             smtpServer->SetUsername( pUser);
00910 
00911                      IMPORT_LOG1( "Created new SMTP server: %s\n", pServer);
00912               }
00913        }
00914 }
00915 
00916 nsresult nsEudoraWin32::GetAttachmentInfo( const char *pFileName, nsIFileSpec *pSpec, nsCString& mimeType, nsCString& aAttachmentName)
00917 {
00918        mimeType.Truncate();
00919        pSpec->SetNativePath( pFileName);
00920        nsresult      rv;
00921        PRBool        isFile = PR_FALSE;
00922        PRBool        exists = PR_FALSE;
00923        if (NS_FAILED( rv = pSpec->Exists( &exists)))
00924               return( rv);
00925        if (NS_FAILED( rv = pSpec->IsFile( &isFile)))
00926               return( rv);
00927        if (exists && isFile) {
00928               char *pLeaf = nsnull;
00929               pSpec->GetLeafName( &pLeaf);
00930               if (!pLeaf)
00931                      return( NS_ERROR_FAILURE);
00932               nsCString name(pLeaf);
00933               nsCRT::free( pLeaf);
00934               if (name.Length() > 4) {
00935                      nsCString ext;
00936                      PRInt32 idx = name.RFindChar( '.');
00937                      if (idx != -1) {
00938                             name.Right( ext, name.Length() - idx);
00939                             GetMimeTypeFromExtension( ext, mimeType);
00940                      }
00941               }
00942               if (mimeType.IsEmpty())
00943                      mimeType = "application/octet-stream";
00944 
00945         // Convert description to unicode.
00946         nsCOMPtr<nsIImportService> impSvc = do_GetService(NS_IMPORTSERVICE_CONTRACTID);
00947         NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get import service");
00948         if (NS_SUCCEEDED(rv)) {
00949             nsAutoString description;
00950             rv = impSvc->SystemStringToUnicode(name.get(), description);
00951             NS_ASSERTION(NS_SUCCEEDED(rv), "failed to convert system string to unicode");
00952             if (NS_SUCCEEDED(rv))
00953                 aAttachmentName = NS_ConvertUTF16toUTF8(description);
00954         }
00955 
00956         if (aAttachmentName.IsEmpty())
00957             aAttachmentName = name;
00958 
00959               return( NS_OK);
00960        }
00961        
00962        return( NS_ERROR_FAILURE);
00963 }
00964 
00965 PRBool nsEudoraWin32::FindMimeIniFile( nsIFileSpec *pSpec)
00966 {
00967        nsCOMPtr<nsIDirectoryIterator>     dir;
00968        nsresult rv = NS_NewDirectoryIterator( getter_AddRefs( dir));
00969        if (NS_FAILED( rv))
00970               return( PR_FALSE);
00971 
00972        PRBool exists = PR_FALSE;
00973        rv = dir->Init( pSpec, PR_TRUE);
00974        if (NS_FAILED( rv))
00975               return( PR_FALSE);
00976 
00977        rv = dir->Exists( &exists);
00978        if (NS_FAILED( rv))
00979               return( PR_FALSE);
00980        
00981        PRBool                             isFile;
00982        nsCOMPtr<nsIFileSpec>       entry;
00983        char *                             pName;
00984        nsCString                          fName;
00985        nsCString                          ext;
00986        nsCString                          name;
00987        PRBool                             found = PR_FALSE;
00988 
00989        while (exists && NS_SUCCEEDED( rv)) {
00990               rv = dir->GetCurrentSpec( getter_AddRefs( entry));
00991               if (NS_SUCCEEDED( rv)) {
00992                      rv = entry->GetLeafName( &pName);
00993                      if (NS_SUCCEEDED( rv) && pName) {
00994                             fName = pName;
00995                             nsCRT::free( pName);
00996                             if (fName.Length() > 4) {
00997                                    fName.Right( ext, 4);
00998                                    fName.Left( name, fName.Length() - 4);
00999                             }
01000                             else {
01001                                    ext.Truncate();
01002                                    name = fName;
01003                             }
01004                             ToLowerCase(ext);
01005                             if (ext.EqualsLiteral(".ini")) {
01006                                    isFile = PR_FALSE;
01007                                    entry->IsFile( &isFile);
01008                                    if (isFile) {
01009                                           if (found) {
01010                                                  // which one of these files is newer?
01011                                                  PRUint32      modDate1, modDate2;
01012                                                  entry->GetModDate( &modDate2);
01013                                                  pSpec->GetModDate( &modDate1);
01014                                                  if (modDate2 > modDate1)
01015                                                         pSpec->FromFileSpec( entry);
01016                                           }
01017                                           else {
01018                                                  pSpec->FromFileSpec( entry);
01019                                                  found = PR_TRUE;
01020                                           }
01021                                    }
01022                             }
01023                      }                           
01024               }
01025               
01026               rv = dir->Next();
01027               if (NS_SUCCEEDED( rv))
01028                      rv = dir->Exists( &exists);
01029        }
01030        
01031        if (found)
01032               return( PR_TRUE);
01033        else
01034               return( PR_FALSE);
01035 }
01036 
01037 
01038 void nsEudoraWin32::GetMimeTypeFromExtension( nsCString& ext, nsCString& mimeType)
01039 {
01040        HKEY   sKey;
01041        if (::RegOpenKeyEx( HKEY_CLASSES_ROOT, ext.get(), 0, KEY_QUERY_VALUE, &sKey) == ERROR_SUCCESS) {
01042               // get the value of "Current"
01043               BYTE *pBytes = GetValueBytes( sKey, "Content Type");
01044               if (pBytes) {
01045                      mimeType = (const char *)pBytes;
01046                      delete [] pBytes;
01047               }
01048               ::RegCloseKey( sKey);
01049        }
01050 
01051        if (!mimeType.IsEmpty() || !m_mailImportLocation || (ext.Length() > 10))
01052               return;
01053        
01054        // TLR: FIXME: We should/could cache the extension to mime type maps we find
01055        // and check the cache first before scanning all of eudora's mappings?
01056 
01057        // It's not in the registry, try and find the .ini file for Eudora's private
01058        // mime type list
01059        if (!m_pMimeSection) {
01060               nsIFileSpec *pSpec;
01061               nsresult rv = NS_NewFileSpec( &pSpec);
01062               if (NS_FAILED( rv) || !pSpec)
01063                      return;
01064 
01065               pSpec->FromFileSpec( m_mailImportLocation);
01066 
01067               pSpec->AppendRelativeUnixPath( "eudora.ini");
01068               PRBool exists = PR_FALSE;
01069               PRBool isFile = PR_FALSE;
01070               rv = pSpec->Exists( &exists);
01071               if (NS_SUCCEEDED( rv))
01072                      rv = pSpec->IsFile( &isFile);
01073               
01074               if (!isFile || !exists) {
01075                      rv = pSpec->FromFileSpec( m_mailImportLocation);
01076                      if (NS_FAILED( rv))
01077                             return;
01078                      if (!FindMimeIniFile( pSpec))
01079                             return;
01080               }
01081 
01082               char *pName = nsnull;
01083               pSpec->GetNativePath( &pName);
01084               if (!pName)
01085                      return;
01086               nsCString     fileName(pName);
01087               nsCRT::free( pName);
01088 
01089               // Read the mime map section
01090               DWORD  size = 1024;
01091               DWORD  dSize = size - 2;
01092               while (dSize == (size - 2)) {
01093                      if (m_pMimeSection)
01094                             delete [] m_pMimeSection;
01095                      size += 1024;
01096                      m_pMimeSection = new char[size];
01097                      dSize = ::GetPrivateProfileSection( "Mappings", m_pMimeSection, size, fileName.get());
01098               }
01099        }
01100 
01101        if (!m_pMimeSection)
01102               return;
01103        
01104        IMPORT_LOG1( "Looking for mime type for extension: %s\n", ext.get());
01105 
01106        // out/in/both=extension,mac creator,mac type,mime type1,mime type2
01107        const char *pExt = ext.get();
01108        pExt++;
01109 
01110        char   *      pChar = m_pMimeSection;
01111        char   *      pStart;
01112        int                  len;
01113        nsCString     tStr;
01114        for(;;) {
01115               while (*pChar != '=') {
01116                      if (!(*pChar) && !(*(pChar + 1)))
01117                             return;
01118                      pChar++;
01119               }
01120               if (*pChar)
01121                      pChar++;
01122               pStart = pChar;
01123               len = 0;
01124               while (*pChar && (*pChar != ',')) {
01125                      pChar++;
01126                      len++;
01127               }
01128               if (!*pChar) return;
01129               tStr.Truncate();
01130               tStr.Append( pStart, len);
01131               tStr.Trim( kWhitespace);
01132               if (!nsCRT::strcasecmp( tStr.get(), pExt)) {
01133                      // skip the mac creator and type
01134                      pChar++;
01135                      while (*pChar && (*pChar != ','))
01136                             pChar++;
01137                      if (!*pChar) return;
01138                      pChar++;
01139                      while (*pChar && (*pChar != ','))
01140                             pChar++;
01141                      if (!*pChar) return;
01142                      pChar++;
01143                      // Get the first mime type
01144                      len = 0;
01145                      pStart = pChar;
01146                      while (*pChar && (*pChar != ',')) {
01147                             pChar++;
01148                             len++;
01149                      }
01150                      if (!*pChar) return;
01151                      pChar++;
01152                      if (!len) continue;
01153                      tStr.Truncate();
01154                      tStr.Append( pStart, len);
01155                      tStr.Trim( kWhitespace);
01156                      if (tStr.IsEmpty()) continue;
01157                      mimeType.Truncate();
01158                      mimeType.Append( tStr.get());
01159                      mimeType.Append( "/");
01160                      pStart = pChar;
01161                      len = 0;
01162                      while (*pChar && (*pChar != 0x0D) && (*pChar != 0x0A)) {
01163                             pChar++;
01164                             len++;
01165                      }
01166                      if (!len) continue;
01167                      tStr.Truncate();
01168                      tStr.Append( pStart, len);
01169                      tStr.Trim( kWhitespace);
01170                      if (tStr.IsEmpty()) continue;
01171                      mimeType.Append( tStr.get());
01172 
01173                      IMPORT_LOG1( "Found Mime Type: %s\n", mimeType.get());
01174 
01175                      return;
01176               }
01177        }      
01178 }
01179 
01180 PRBool nsEudoraWin32::FindAddressFolder( nsIFileSpec *pFolder)
01181 {
01182        IMPORT_LOG0( "*** Looking for Eudora address folder\n");
01183 
01184        return( FindEudoraLocation( pFolder));
01185 }
01186 
01187 nsresult nsEudoraWin32::FindAddressBooks( nsIFileSpec *pRoot, nsISupportsArray **ppArray)
01188 {
01189 
01190        nsCOMPtr<nsIFileSpec>       spec;
01191        nsresult rv = NS_NewFileSpec( getter_AddRefs( spec));
01192        if (NS_FAILED( rv))
01193               return( rv);
01194        rv = spec->FromFileSpec( pRoot);
01195        if (NS_FAILED( rv))
01196               return( rv);
01197 
01198        rv = NS_NewISupportsArray( ppArray);
01199        if (NS_FAILED( rv)) {
01200               IMPORT_LOG0( "FAILED to allocate the nsISupportsArray\n");
01201               return( rv);
01202        }
01203               
01204        nsCOMPtr<nsIImportService> impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
01205        if (NS_FAILED( rv))
01206               return( rv);
01207        
01208        NS_IF_RELEASE( m_addressImportFolder);
01209        m_addressImportFolder = pRoot;
01210        NS_IF_ADDREF( pRoot);
01211 
01212        
01213        nsString             displayName;
01214        nsEudoraStringBundle::GetStringByID( EUDORAIMPORT_NICKNAMES_NAME, displayName);
01215 
01216        // First off, get the default nndbase.txt, then scan the default nicknames subdir,
01217        // then look in the .ini file for additional directories to scan for address books!
01218        rv = spec->AppendRelativeUnixPath( "nndbase.txt");
01219        PRBool exists = PR_FALSE;
01220        PRBool isFile = PR_FALSE;
01221        if (NS_SUCCEEDED( rv))
01222               rv = spec->Exists( &exists);
01223        if (NS_SUCCEEDED( rv) && exists)
01224               rv = spec->IsFile( &isFile);
01225        if (exists && isFile) {
01226               if (NS_FAILED( rv = FoundAddressBook( spec, displayName.get(), *ppArray, impSvc)))
01227                      return( rv);
01228        }
01229        
01230        // Try the default directory
01231        rv = spec->FromFileSpec( pRoot);
01232        if (NS_FAILED( rv))
01233               return( rv);
01234        rv = spec->AppendRelativeUnixPath( "Nickname");
01235        PRBool isDir = PR_FALSE;
01236        exists = PR_FALSE;
01237        if (NS_SUCCEEDED( rv))
01238               rv = spec->Exists( &exists);
01239        if (NS_SUCCEEDED( rv) && exists)
01240               rv = spec->IsDirectory( &isDir);
01241        if (exists && isDir) {
01242               if (NS_FAILED( rv = ScanAddressDir( spec, *ppArray, impSvc)))
01243                      return( rv);
01244        }
01245        
01246        // Try the ini file to find other directories!
01247        rv = spec->FromFileSpec( pRoot);
01248        if (NS_SUCCEEDED( rv))
01249               rv = spec->AppendRelativeUnixPath( "eudora.ini");
01250        exists = PR_FALSE;
01251        isFile = PR_FALSE;
01252        if (NS_SUCCEEDED( rv))
01253               rv = spec->Exists( &exists);
01254        if (NS_SUCCEEDED( rv) && exists)
01255               rv = spec->IsFile( &isFile);
01256        
01257        if (!isFile || !exists) {
01258               rv = spec->FromFileSpec( pRoot);
01259               if (NS_FAILED( rv))
01260                      return( NS_OK);
01261               if (!FindMimeIniFile( spec))
01262                      return( NS_OK);
01263        }
01264 
01265        char *pName = nsnull;
01266        spec->GetNativePath( &pName);
01267        if (!pName)
01268               return( NS_OK);
01269        nsCString     fileName(pName);
01270        nsCRT::free( pName);
01271        
01272        // This is the supposed ini file name!
01273        // Get the extra directories for nicknames and parse it for valid nickname directories
01274        // to look into...
01275        char *pBuffer = new char[2048];
01276        DWORD len = ::GetPrivateProfileString( "Settings", "ExtraNicknameDirs", "", pBuffer, 2048, fileName.get());
01277        if (len == 2047) {
01278               // If the value is really that large then don't bother!
01279               delete [] pBuffer;
01280               return( NS_OK);
01281        }
01282        nsCString     dirs(pBuffer);
01283        delete [] pBuffer;
01284        dirs.Trim( kWhitespace);
01285        PRInt32       idx = 0;
01286        nsCString     currentDir;
01287        while ((idx = dirs.FindChar( ';')) != -1) {
01288               dirs.Left( currentDir, idx);
01289               currentDir.Trim( kWhitespace);
01290               if (!currentDir.IsEmpty()) {
01291                      rv = spec->SetNativePath( currentDir.get());
01292                      exists = PR_FALSE;
01293                      isDir = PR_FALSE;
01294                      if (NS_SUCCEEDED( rv))
01295                             rv = spec->Exists( &exists);
01296                      if (NS_SUCCEEDED( rv) && exists)
01297                             rv = spec->IsDirectory( &isDir);
01298                      if (exists && isDir) {
01299                             if (NS_FAILED( rv = ScanAddressDir( spec, *ppArray, impSvc)))
01300                                    return( rv);
01301                      }
01302               }
01303               dirs.Right( currentDir, dirs.Length() - idx - 1);
01304               dirs = currentDir;
01305               dirs.Trim( kWhitespace);
01306        }
01307        if (!dirs.IsEmpty()) {
01308               rv = spec->SetNativePath( dirs.get());
01309               exists = PR_FALSE;
01310               isDir = PR_FALSE;
01311               if (NS_SUCCEEDED( rv))
01312                      rv = spec->Exists( &exists);
01313               if (NS_SUCCEEDED( rv) && exists)
01314                      rv = spec->IsDirectory( &isDir);
01315               if (exists && isDir) {
01316                      if (NS_FAILED( rv = ScanAddressDir( spec, *ppArray, impSvc)))
01317                             return( rv);
01318               }
01319        }
01320        
01321        return( NS_OK);
01322 }
01323 
01324 
01325 nsresult nsEudoraWin32::ScanAddressDir( nsIFileSpec *pDir, nsISupportsArray *pArray, nsIImportService *impSvc)
01326 {
01327        nsCOMPtr<nsIDirectoryIterator>     dir;
01328        nsresult rv = NS_NewDirectoryIterator( getter_AddRefs( dir));
01329        if (NS_FAILED( rv))
01330               return( rv);
01331 
01332        PRBool exists = PR_FALSE;
01333        rv = dir->Init( pDir, PR_TRUE);
01334        if (NS_FAILED( rv))
01335               return( rv);
01336 
01337        rv = dir->Exists( &exists);
01338        if (NS_FAILED( rv))
01339               return( rv);
01340        
01341        PRBool                             isFile;
01342        nsCOMPtr<nsIFileSpec>       entry;
01343        char *                             pName;
01344        nsCString                          fName;
01345        nsCString                          ext;
01346        nsCString                          name;
01347 
01348        while (exists && NS_SUCCEEDED( rv)) {
01349               rv = dir->GetCurrentSpec( getter_AddRefs( entry));
01350               if (NS_SUCCEEDED( rv)) {
01351                      rv = entry->GetLeafName( &pName);
01352                      if (NS_SUCCEEDED( rv) && pName) {
01353                             fName = pName;
01354                             nsCRT::free( pName);
01355                             if (fName.Length() > 4) {
01356                                    fName.Right( ext, 4);
01357                                    fName.Left( name, fName.Length() - 4);
01358                             }
01359                             else {
01360                                    ext.Truncate();
01361                                    name = fName;
01362                             }
01363                             ToLowerCase(ext);
01364                             if (ext.EqualsLiteral(".txt")) {
01365                                    isFile = PR_FALSE;
01366                                    entry->IsFile( &isFile);
01367                                    if (isFile) {
01368                                           rv = FoundAddressBook( entry, nsnull, pArray, impSvc);
01369                                           if (NS_FAILED( rv))
01370                                                  return( rv);
01371                                    }
01372                             }
01373                      }                           
01374               }
01375               
01376               rv = dir->Next();
01377               if (NS_SUCCEEDED( rv))
01378                      rv = dir->Exists( &exists);
01379        }
01380 
01381        return( rv);
01382 }
01383 
01384 
01385 nsresult nsEudoraWin32::FoundAddressBook( nsIFileSpec *spec, const PRUnichar *pName, nsISupportsArray *pArray, nsIImportService *impSvc)
01386 {
01387        nsCOMPtr<nsIImportABDescriptor>    desc;
01388        nsISupports *                             pInterface;
01389        nsString                                         name;
01390        nsresult                                         rv;
01391 
01392        if (pName)
01393               name = pName;
01394        else {
01395               char *pLeaf = nsnull;
01396               rv = spec->GetLeafName( &pLeaf);
01397               if (NS_FAILED( rv))
01398                      return( rv);
01399               if (!pLeaf)
01400                      return( NS_ERROR_FAILURE);
01401               NS_CopyNativeToUnicode(nsDependentCString(pLeaf), name);
01402               nsCRT::free( pLeaf);
01403               nsString      tStr;
01404               name.Right( tStr, 4);
01405               if (tStr.LowerCaseEqualsLiteral(".txt")) {
01406                      name.Left( tStr, name.Length() - 4);
01407                      name = tStr;
01408               }
01409        }
01410 
01411        rv = impSvc->CreateNewABDescriptor( getter_AddRefs( desc));
01412        if (NS_SUCCEEDED( rv)) {
01413               PRUint32 sz = 0;
01414               spec->GetFileSize( &sz);    
01415               desc->SetPreferredName( name.get());
01416               desc->SetSize( sz);
01417               nsIFileSpec *pSpec = nsnull;
01418               desc->GetFileSpec( &pSpec);
01419               if (pSpec) {
01420                      pSpec->FromFileSpec( spec);
01421                      NS_RELEASE( pSpec);
01422               }
01423               rv = desc->QueryInterface( kISupportsIID, (void **) &pInterface);
01424               pArray->AppendElement( pInterface);
01425               pInterface->Release();
01426        }
01427        if (NS_FAILED( rv)) {
01428               IMPORT_LOG0( "*** Error creating address book descriptor for eudora\n");
01429               return( rv);
01430        }
01431 
01432        return( NS_OK);
01433 }
01434 
01435 
01436 void nsEudoraWin32::ConvertPath( nsCString& str)
01437 {
01438        nsCString     temp;
01439        nsCString     path;
01440        PRInt32              idx = 0;
01441        PRInt32              start = 0;
01442        nsCString     search;
01443 
01444        idx = str.FindChar( '\\', idx);
01445        if ((idx == 2) && (str.CharAt( 1) == ':')) {
01446               str.Left( path, 3);
01447               idx++;
01448               idx = str.FindChar( '\\', idx);
01449               start = 3;
01450               if ((idx == -1) && (str.Length() > 3)) {
01451                      str.Right( temp, str.Length() - start);
01452                      path.Append( temp);
01453               }
01454        }
01455        
01456        WIN32_FIND_DATA findFileData;
01457        while (idx != -1) {
01458               str.Mid( temp, start, idx - start);
01459               search = path;
01460               search.Append( temp);
01461               HANDLE h = FindFirstFile( search.get(), &findFileData);
01462               if (h == INVALID_HANDLE_VALUE)
01463                      return;
01464               path.Append( findFileData.cFileName);
01465               idx++;
01466               start = idx;
01467               idx = str.FindChar( '\\', idx);
01468               FindClose( h);
01469               if (idx != -1)
01470                      path.Append( '\\');
01471               else {
01472                      str.Right( temp, str.Length() - start);
01473                      path.Append( '\\');
01474                      path.Append( temp);
01475               }
01476        }
01477 
01478        str = path;
01479 }
01480