/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org Code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Pierre Phaneuf * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsCOMPtr.h" #include "nsReadableUtils.h" #include "nsIComponentManager.h" #include "nsIServiceManager.h" #include "nsIMsgAccountManager.h" #include "nsIMsgAccount.h" #include "nsIPop3IncomingServer.h" #include "nsMsgBaseCID.h" #include "nsMsgCompCID.h" #include "nsISmtpService.h" #include "nsISmtpServer.h" #include "nsEudoraWin32.h" #include "nsIImportService.h" #include "nsIImportMailboxDescriptor.h" #include "nsIImportABDescriptor.h" #include "nsEudoraStringBundle.h" #include "nsEudoraImport.h" #include "nsUnicharUtils.h" #include "EudoraDebugLog.h" static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static const char * kWhitespace = "\b\t\r\n "; // ::RegOpenKeyEx( HKEY_CURRENT_USER, "Software\\Accounts", 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &sKey) == ERROR_SUCCESS) BYTE * nsEudoraWin32::GetValueBytes( HKEY hKey, const char *pValueName) { LONG err; DWORD bufSz; LPBYTE pBytes = NULL; err = ::RegQueryValueEx( hKey, pValueName, NULL, NULL, NULL, &bufSz); if (err == ERROR_SUCCESS) { pBytes = new BYTE[bufSz]; err = ::RegQueryValueEx( hKey, pValueName, NULL, NULL, pBytes, &bufSz); if (err != ERROR_SUCCESS) { delete [] pBytes; pBytes = NULL; } } return( pBytes); } nsEudoraWin32::nsEudoraWin32() { m_mailImportLocation = nsnull; m_addressImportFolder = nsnull; m_pMimeSection = nsnull; } nsEudoraWin32::~nsEudoraWin32() { NS_IF_RELEASE( m_mailImportLocation); NS_IF_RELEASE( m_addressImportFolder); if (m_pMimeSection) delete [] m_pMimeSection; } PRBool nsEudoraWin32::FindMailFolder( nsIFileSpec *pFolder) { return( FindEudoraLocation( pFolder)); } PRBool nsEudoraWin32::FindEudoraLocation( nsIFileSpec *pFolder, PRBool findIni) { PRBool result = PR_FALSE; PRBool exists = PR_FALSE; // look in the registry to see where eudora is installed? HKEY sKey; if (::RegOpenKeyEx( HKEY_CURRENT_USER, "Software\\Qualcomm\\Eudora\\CommandLine", 0, KEY_QUERY_VALUE, &sKey) == ERROR_SUCCESS) { // get the value of "Current" BYTE *pBytes = GetValueBytes( sKey, "Current"); if (pBytes) { nsCString str((const char *)pBytes); delete [] pBytes; str.CompressWhitespace(); // Command line is Eudora mailfolder eudora.ini if (findIni) { // find the string coming after the last space PRInt32 index = str.RFind(" "); if (index != -1) { index++; // skip the space nsCString path; str.Mid( path, index, str.Length() - index); pFolder->SetNativePath( path.get()); pFolder->IsFile( &exists); if (exists) result = exists; else // it may just be the mailbox location....guess that there will be a eudora.ini file there { pFolder->AppendRelativeUnixPath("eudora.ini"); pFolder->IsFile( &exists); result = exists; } } } // if findIni else { int idx = -1; if (str.CharAt( 0) == '"') { idx = str.FindChar( '"', 1); if (idx != -1) idx++; } else { idx = str.FindChar( ' '); } if (idx != -1) { idx++; while (str.CharAt( idx) == ' ') idx++; int endIdx = -1; if (str.CharAt( idx) == '"') { endIdx = str.FindChar( '"', idx); } else { endIdx = str.FindChar( ' ', idx); } if (endIdx != -1) { nsCString path; str.Mid( path, idx, endIdx - idx); pFolder->SetNativePath( path.get()); if (NS_SUCCEEDED( pFolder->IsDirectory( &exists))) result = exists; } } } } // if pBytes ::RegCloseKey( sKey); } return( result); } nsresult nsEudoraWin32::FindMailboxes( nsIFileSpec *pRoot, nsISupportsArray **ppArray) { nsresult rv = NS_NewISupportsArray( ppArray); if (NS_FAILED( rv)) { IMPORT_LOG0( "FAILED to allocate the nsISupportsArray\n"); return( rv); } nsCOMPtr impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv)); if (NS_FAILED( rv)) return( rv); m_depth = 0; NS_IF_RELEASE( m_mailImportLocation); m_mailImportLocation = pRoot; NS_IF_ADDREF( m_mailImportLocation); return( ScanMailDir( pRoot, *ppArray, impSvc)); } nsresult nsEudoraWin32::ScanMailDir( nsIFileSpec *pFolder, nsISupportsArray *pArray, nsIImportService *pImport) { PRBool exists = PR_FALSE; PRBool isFile = PR_FALSE; char * pContents = nsnull; PRInt32 len = 0; nsCOMPtr descMap; nsresult rv; if (NS_FAILED( rv = NS_NewFileSpec( getter_AddRefs( descMap)))) return( rv); m_depth++; descMap->FromFileSpec( pFolder); rv = descMap->AppendRelativeUnixPath( "descmap.pce"); if (NS_SUCCEEDED( rv)) rv = descMap->IsFile( &isFile); if (NS_SUCCEEDED( rv)) rv = descMap->Exists( &exists); if (NS_SUCCEEDED( rv) && exists && isFile) { rv = descMap->GetFileContents( &pContents); if (NS_SUCCEEDED( rv) && pContents) { len = strlen( pContents); if (NS_SUCCEEDED( rv)) rv = ScanDescmap( pFolder, pArray, pImport, pContents, len); nsCRT::free( pContents); } else rv = NS_ERROR_FAILURE; } if (NS_FAILED( rv) || !isFile || !exists) rv = IterateMailDir( pFolder, pArray, pImport); m_depth--; return( rv); } nsresult nsEudoraWin32::IterateMailDir( nsIFileSpec *pFolder, nsISupportsArray *pArray, nsIImportService *pImport) { nsCOMPtr dir; nsresult rv = NS_NewDirectoryIterator( getter_AddRefs( dir)); if (NS_FAILED( rv)) return( rv); PRBool exists = PR_FALSE; rv = dir->Init( pFolder, PR_TRUE); if (NS_FAILED( rv)) return( rv); rv = dir->Exists( &exists); if (NS_FAILED( rv)) return( rv); PRBool isFolder; PRBool isFile; nsCOMPtr entry; char * pName; nsCString fName; nsCString ext; nsCString name; while (exists && NS_SUCCEEDED( rv)) { rv = dir->GetCurrentSpec( getter_AddRefs( entry)); if (NS_SUCCEEDED( rv)) { rv = entry->GetLeafName( &pName); if (NS_SUCCEEDED( rv) && pName) { fName = pName; nsCRT::free( pName); if (fName.Length() > 4) { fName.Right( ext, 4); fName.Left( name, fName.Length() - 4); } else { ext.Truncate(); name = fName; } ToLowerCase(ext); if (ext.EqualsLiteral(".fol")) { isFolder = PR_FALSE; entry->IsDirectory( &isFolder); if (isFolder) { // add the folder rv = FoundMailFolder( entry, name.get(), pArray, pImport); if (NS_SUCCEEDED( rv)) { rv = ScanMailDir( entry, pArray, pImport); if (NS_FAILED( rv)) { IMPORT_LOG0( "*** Error scanning mail directory\n"); } } } } else if (ext.EqualsLiteral(".mbx")) { isFile = PR_FALSE; entry->IsFile( &isFile); if (isFile) { rv = FoundMailbox( entry, name.get(), pArray, pImport); } } } } rv = dir->Next(); if (NS_SUCCEEDED( rv)) rv = dir->Exists( &exists); } return( rv); } nsresult nsEudoraWin32::ScanDescmap( nsIFileSpec *pFolder, nsISupportsArray *pArray, nsIImportService *pImport, const char *pData, PRInt32 len) { // use this to find stuff in the directory. nsCOMPtr entry; nsresult rv; if (NS_FAILED( rv = NS_NewFileSpec( getter_AddRefs( entry)))) return( rv); // format is Name,FileName,Type,Flag? // Type = M or S for mailbox // = F for folder PRInt32 fieldLen; PRInt32 pos = 0; const char * pStart; nsCString name; nsCString fName; nsCString type; nsCString flag; PRBool isFile; PRBool isFolder; while (pos < len) { pStart = pData; fieldLen = 0; while ((pos < len) && (*pData != ',')) { pos++; pData++; fieldLen++; } name.Truncate(); if (fieldLen) name.Append( pStart, fieldLen); name.Trim( kWhitespace); pos++; pData++; pStart = pData; fieldLen = 0; while ((pos < len) && (*pData != ',')) { pos++; pData++; fieldLen++; } fName.Truncate(); if (fieldLen) fName.Append( pStart, fieldLen); fName.Trim( kWhitespace); pos++; pData++; pStart = pData; fieldLen = 0; while ((pos < len) && (*pData != ',')) { pos++; pData++; fieldLen++; } type.Truncate(); if (fieldLen) type.Append( pStart, fieldLen); type.Trim( kWhitespace); pos++; pData++; pStart = pData; fieldLen = 0; while ((pos < len) && (*pData != 0x0D) && (*pData != 0x0A) && (*pData != ',')) { pos++; pData++; fieldLen++; } flag.Truncate(); if (fieldLen) flag.Append( pStart, fieldLen); flag.Trim( kWhitespace); while ((pos < len) && ((*pData == 0x0D) || (*pData == 0x0A))) { pos++; pData++; } IMPORT_LOG2( "name: %s, fName: %s\n", name.get(), fName.get()); if (!fName.IsEmpty() && !name.IsEmpty() && (type.Length() == 1)) { entry->FromFileSpec( pFolder); rv = entry->AppendRelativeUnixPath( fName.get()); if (NS_SUCCEEDED( rv)) { if (type.CharAt( 0) == 'F') { isFolder = PR_FALSE; entry->IsDirectory( &isFolder); if (isFolder) { rv = FoundMailFolder( entry, name.get(), pArray, pImport); if (NS_SUCCEEDED( rv)) { rv = ScanMailDir( entry, pArray, pImport); if (NS_FAILED( rv)) { IMPORT_LOG0( "*** Error scanning mail directory\n"); } } } } else if ((type.CharAt( 0) == 'M') || (type.CharAt( 0) == 'S')) { isFile = PR_FALSE; entry->IsFile( &isFile); if (isFile) { FoundMailbox( entry, name.get(), pArray, pImport); } } } } } return( NS_OK); } nsresult nsEudoraWin32::FoundMailbox( nsIFileSpec *mailFile, const char *pName, nsISupportsArray *pArray, nsIImportService *pImport) { nsString displayName; nsCOMPtr desc; nsISupports * pInterface; NS_CopyNativeToUnicode(nsDependentCString(pName), displayName); #ifdef IMPORT_DEBUG char *pPath = nsnull; mailFile->GetNativePath( &pPath); if (pPath) { IMPORT_LOG2( "Found eudora mailbox, %s: %s\n", pPath, pName); nsCRT::free( pPath); } else { IMPORT_LOG1( "Found eudora mailbox, %s\n", pName); } IMPORT_LOG1( "\tm_depth = %d\n", (int)m_depth); #endif nsresult rv = pImport->CreateNewMailboxDescriptor( getter_AddRefs( desc)); if (NS_SUCCEEDED( rv)) { PRUint32 sz = 0; mailFile->GetFileSize( &sz); desc->SetDisplayName( displayName.get()); desc->SetDepth( m_depth); desc->SetSize( sz); nsIFileSpec *pSpec = nsnull; desc->GetFileSpec( &pSpec); if (pSpec) { pSpec->FromFileSpec( mailFile); NS_RELEASE( pSpec); } rv = desc->QueryInterface( kISupportsIID, (void **) &pInterface); pArray->AppendElement( pInterface); pInterface->Release(); } return( NS_OK); } nsresult nsEudoraWin32::FoundMailFolder( nsIFileSpec *mailFolder, const char *pName, nsISupportsArray *pArray, nsIImportService *pImport) { nsString displayName; nsCOMPtr desc; nsISupports * pInterface; NS_CopyNativeToUnicode(nsDependentCString(pName), displayName); #ifdef IMPORT_DEBUG char *pPath = nsnull; mailFolder->GetNativePath( &pPath); if (pPath) { IMPORT_LOG2( "Found eudora folder, %s: %s\n", pPath, pName); nsCRT::free( pPath); } else { IMPORT_LOG1( "Found eudora folder, %s\n", pName); } IMPORT_LOG1( "\tm_depth = %d\n", (int)m_depth); #endif nsresult rv = pImport->CreateNewMailboxDescriptor( getter_AddRefs( desc)); if (NS_SUCCEEDED( rv)) { PRUint32 sz = 0; desc->SetDisplayName( displayName.get()); desc->SetDepth( m_depth); desc->SetSize( sz); nsIFileSpec *pSpec = nsnull; desc->GetFileSpec( &pSpec); if (pSpec) { pSpec->FromFileSpec( mailFolder); NS_RELEASE( pSpec); } rv = desc->QueryInterface( kISupportsIID, (void **) &pInterface); pArray->AppendElement( pInterface); pInterface->Release(); } return( NS_OK); } nsresult nsEudoraWin32::FindTOCFile( nsIFileSpec *pMailFile, nsIFileSpec **ppTOCFile, PRBool *pDeleteToc) { nsresult rv; char * pName = nsnull; *pDeleteToc = PR_FALSE; *ppTOCFile = nsnull; rv = pMailFile->GetLeafName( &pName); if (NS_FAILED( rv)) return( rv); rv = pMailFile->GetParent( ppTOCFile); if (NS_FAILED( rv)) return( rv); nsCString leaf(pName); nsCRT::free( pName); nsCString name; if ((leaf.Length() > 4) && (leaf.CharAt( leaf.Length() - 4) == '.')) leaf.Left( name, leaf.Length() - 4); else name = leaf; name.Append( ".toc"); rv = (*ppTOCFile)->AppendRelativeUnixPath( name.get()); if (NS_FAILED( rv)) return( rv); PRBool exists = PR_FALSE; rv = (*ppTOCFile)->Exists( &exists); if (NS_FAILED( rv)) return( rv); PRBool isFile = PR_FALSE; rv = (*ppTOCFile)->IsFile( &isFile); if (NS_FAILED( rv)) return( rv); if (exists && isFile) return( NS_OK); return( NS_ERROR_FAILURE); } PRBool nsEudoraWin32::ImportSettings( nsIFileSpec *pIniFile, nsIMsgAccount **localMailAccount) { PRBool result = PR_FALSE; nsresult rv; nsCOMPtr accMgr = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv); if (NS_FAILED(rv)) { IMPORT_LOG0( "*** Failed to create a account manager!\n"); return( PR_FALSE); } // Eudora info is arranged by key, 1 for the default, then persona's for additional // accounts. // Start with the first one, then do each persona char *pIniPath = nsnull; pIniFile->GetNativePath( &pIniPath); if (!pIniPath) return( PR_FALSE); nsCString iniPath(pIniPath); nsCRT::free( pIniPath); UINT valInt; SimpleBufferTonyRCopiedOnce section; DWORD sSize; DWORD sOffset = 0; DWORD start; nsCString sectionName("Settings"); int popCount = 0; int accounts = 0; DWORD allocSize = 0; do { allocSize += 2048; section.Allocate( allocSize); sSize = ::GetPrivateProfileSection( "Personalities", section.m_pBuffer, allocSize, iniPath.get()); } while (sSize == (allocSize - 2)); nsIMsgAccount * pAccount; do { if (!sectionName.IsEmpty()) { pAccount = nsnull; valInt = ::GetPrivateProfileInt( sectionName.get(), "UsesPOP", 1, iniPath.get()); if (valInt) { // This is a POP account if (BuildPOPAccount( accMgr, sectionName.get(), iniPath.get(), &pAccount)) { accounts++; popCount++; if (popCount > 1) { if (localMailAccount && *localMailAccount) { NS_RELEASE( *localMailAccount); *localMailAccount = nsnull; } } else { if (localMailAccount) { *localMailAccount = pAccount; NS_IF_ADDREF( pAccount); } } } } else { valInt = ::GetPrivateProfileInt( sectionName.get(), "UsesIMAP", 0, iniPath.get()); if (valInt) { // This is an IMAP account if (BuildIMAPAccount( accMgr, sectionName.get(), iniPath.get(), &pAccount)) { accounts++; } } } if (pAccount && (sOffset == 0)) { accMgr->SetDefaultAccount( pAccount); } NS_IF_RELEASE( pAccount); } sectionName.Truncate(); while ((sOffset < sSize) && (section.m_pBuffer[sOffset] != '=')) sOffset++; sOffset++; start = sOffset; while ((sOffset < sSize) && (section.m_pBuffer[sOffset] != 0)) sOffset++; if (sOffset > start) { sectionName.Append( section.m_pBuffer + start, sOffset - start); sectionName.Trim( kWhitespace); } } while (sOffset < sSize); // Now save the new acct info to pref file. rv = accMgr->SaveAccountInfo(); NS_ASSERTION(NS_SUCCEEDED(rv), "Can't save account info to pref file"); return( accounts != 0); } // maximium size of settings strings #define kIniValueSize 384 void nsEudoraWin32::GetServerAndUserName( const char *pSection, const char *pIni, nsCString& serverName, nsCString& userName, char *pBuff) { DWORD valSize; int idx; nsCString tStr; serverName.Truncate(); userName.Truncate(); valSize = ::GetPrivateProfileString( pSection, "PopServer", "", pBuff, kIniValueSize, pIni); if (valSize) serverName = pBuff; else { valSize = ::GetPrivateProfileString( pSection, "POPAccount", "", pBuff, kIniValueSize, pIni); if (valSize) { serverName = pBuff; idx = serverName.FindChar( '@'); if (idx != -1) { serverName.Right( tStr, serverName.Length() - idx - 1); serverName = tStr; } } } valSize = ::GetPrivateProfileString( pSection, "LoginName", "", pBuff, kIniValueSize, pIni); if (valSize) userName = pBuff; else { valSize = ::GetPrivateProfileString( pSection, "POPAccount", "", pBuff, kIniValueSize, pIni); if (valSize) { userName = pBuff; idx = userName.FindChar( '@'); if (idx != -1) { userName.Left( tStr, idx); userName = tStr; } } } } void nsEudoraWin32::GetAccountName( const char *pSection, nsString& str) { str.Truncate(); nsCString s(pSection); if (s.Equals(NS_LITERAL_CSTRING("Settings"), nsCaseInsensitiveCStringComparator())) { str.AssignLiteral("Eudora "); str.AppendWithConversion( pSection); } else { nsCString tStr; str.AssignWithConversion(pSection); if (s.Length() > 8) { s.Left( tStr, 8); if (tStr.Equals(NS_LITERAL_CSTRING("Persona-"), nsCaseInsensitiveCStringComparator())) { s.Right( tStr, s.Length() - 8); str.AssignWithConversion(tStr.get()); } } } } PRBool nsEudoraWin32::BuildPOPAccount( nsIMsgAccountManager *accMgr, const char *pSection, const char *pIni, nsIMsgAccount **ppAccount) { if (ppAccount) *ppAccount = nsnull; char valBuff[kIniValueSize]; nsCString serverName; nsCString userName; GetServerAndUserName( pSection, pIni, serverName, userName, valBuff); if (serverName.IsEmpty() || userName.IsEmpty()) return( PR_FALSE); PRBool result = PR_FALSE; // I now have a user name/server name pair, find out if it already exists? nsCOMPtr in; nsresult rv = accMgr->FindServer( userName.get(), serverName.get(), "pop3", getter_AddRefs( in)); if (NS_FAILED( rv) || (in == nsnull)) { // Create the incoming server and an account for it? rv = accMgr->CreateIncomingServer( userName.get(), serverName.get(), "pop3", getter_AddRefs( in)); if (NS_SUCCEEDED( rv) && in) { rv = in->SetType( "pop3"); // rv = in->SetHostName( serverName); // rv = in->SetUsername( userName); IMPORT_LOG2( "Created POP3 server named: %s, userName: %s\n", serverName.get(), userName.get()); nsString prettyName; GetAccountName( pSection, prettyName); PRUnichar *pretty = ToNewUnicode(prettyName); IMPORT_LOG1( "\tSet pretty name to: %S\n", pretty); rv = in->SetPrettyName( pretty); nsCRT::free( pretty); // We have a server, create an account. nsCOMPtr account; rv = accMgr->CreateAccount( getter_AddRefs( account)); if (NS_SUCCEEDED( rv) && account) { rv = account->SetIncomingServer( in); IMPORT_LOG0( "Created a new account and set the incoming server to the POP3 server.\n"); nsCOMPtr pop3Server = do_QueryInterface(in, &rv); NS_ENSURE_SUCCESS(rv,rv); UINT valInt = ::GetPrivateProfileInt(pSection, "LeaveMailOnServer", 0, pIni); pop3Server->SetLeaveMessagesOnServer(valInt ? PR_TRUE : PR_FALSE); // Fiddle with the identities SetIdentities(accMgr, account, pSection, pIni, userName.get(), serverName.get(), valBuff); result = PR_TRUE; if (ppAccount) account->QueryInterface( NS_GET_IID(nsIMsgAccount), (void **)ppAccount); } } } else result = PR_TRUE; return( result); } PRBool nsEudoraWin32::BuildIMAPAccount( nsIMsgAccountManager *accMgr, const char *pSection, const char *pIni, nsIMsgAccount **ppAccount) { char valBuff[kIniValueSize]; nsCString serverName; nsCString userName; GetServerAndUserName( pSection, pIni, serverName, userName, valBuff); if (serverName.IsEmpty() || userName.IsEmpty()) return( PR_FALSE); PRBool result = PR_FALSE; nsCOMPtr in; nsresult rv = accMgr->FindServer( userName.get(), serverName.get(), "imap", getter_AddRefs( in)); if (NS_FAILED( rv) || (in == nsnull)) { // Create the incoming server and an account for it? rv = accMgr->CreateIncomingServer( userName.get(), serverName.get(), "imap", getter_AddRefs( in)); if (NS_SUCCEEDED( rv) && in) { rv = in->SetType( "imap"); // rv = in->SetHostName( serverName); // rv = in->SetUsername( userName); IMPORT_LOG2( "Created IMAP server named: %s, userName: %s\n", serverName.get(), userName.get()); nsString prettyName; GetAccountName( pSection, prettyName); PRUnichar *pretty = ToNewUnicode(prettyName); IMPORT_LOG1( "\tSet pretty name to: %S\n", pretty); rv = in->SetPrettyName( pretty); nsCRT::free( pretty); // We have a server, create an account. nsCOMPtr account; rv = accMgr->CreateAccount( getter_AddRefs( account)); if (NS_SUCCEEDED( rv) && account) { rv = account->SetIncomingServer( in); IMPORT_LOG0( "Created an account and set the IMAP server as the incoming server\n"); // Fiddle with the identities SetIdentities(accMgr, account, pSection, pIni, userName.get(), serverName.get(), valBuff); result = PR_TRUE; if (ppAccount) account->QueryInterface( NS_GET_IID(nsIMsgAccount), (void **)ppAccount); } } } else result = PR_TRUE; return( result); } void nsEudoraWin32::SetIdentities(nsIMsgAccountManager *accMgr, nsIMsgAccount *acc, const char *pSection, const char *pIniFile, const char *userName, const char *serverName, char *pBuff) { nsCAutoString realName; nsCAutoString email; nsCAutoString server; DWORD valSize; nsresult rv; valSize = ::GetPrivateProfileString( pSection, "RealName", "", pBuff, kIniValueSize, pIniFile); if (valSize) realName = pBuff; valSize = ::GetPrivateProfileString( pSection, "SMTPServer", "", pBuff, kIniValueSize, pIniFile); if (valSize) server = pBuff; valSize = ::GetPrivateProfileString( pSection, "ReturnAddress", "", pBuff, kIniValueSize, pIniFile); if (valSize) email = pBuff; nsCOMPtr id; rv = accMgr->CreateIdentity( getter_AddRefs( id)); if (id) { nsAutoString fullName; fullName.AssignWithConversion(realName.get()); id->SetFullName( fullName.get()); id->SetIdentityName( fullName.get()); if (email.IsEmpty()) { email = userName; email += "@"; email += serverName; } id->SetEmail(email.get()); acc->AddIdentity( id); IMPORT_LOG0( "Created identity and added to the account\n"); IMPORT_LOG1( "\tname: %s\n", realName.get()); IMPORT_LOG1( "\temail: %s\n", email.get()); } SetSmtpServer( accMgr, acc, server.get(), userName); } void nsEudoraWin32::SetSmtpServer( nsIMsgAccountManager *pMgr, nsIMsgAccount *pAcc, const char *pServer, const char *pUser) { nsresult rv; nsCOMPtr smtpService(do_GetService(NS_SMTPSERVICE_CONTRACTID, &rv)); if (NS_SUCCEEDED(rv) && smtpService) { nsCOMPtr foundServer; rv = smtpService->FindServer( pUser, pServer, getter_AddRefs( foundServer)); if (NS_SUCCEEDED( rv) && foundServer) { IMPORT_LOG1( "SMTP server already exists: %s\n", pServer); return; } nsCOMPtr smtpServer; rv = smtpService->CreateSmtpServer( getter_AddRefs( smtpServer)); if (NS_SUCCEEDED( rv) && smtpServer) { smtpServer->SetHostname( pServer); if (pUser) smtpServer->SetUsername( pUser); IMPORT_LOG1( "Created new SMTP server: %s\n", pServer); } } } nsresult nsEudoraWin32::GetAttachmentInfo( const char *pFileName, nsIFileSpec *pSpec, nsCString& mimeType, nsCString& aAttachmentName) { mimeType.Truncate(); pSpec->SetNativePath( pFileName); nsresult rv; PRBool isFile = PR_FALSE; PRBool exists = PR_FALSE; if (NS_FAILED( rv = pSpec->Exists( &exists))) return( rv); if (NS_FAILED( rv = pSpec->IsFile( &isFile))) return( rv); if (exists && isFile) { char *pLeaf = nsnull; pSpec->GetLeafName( &pLeaf); if (!pLeaf) return( NS_ERROR_FAILURE); nsCString name(pLeaf); nsCRT::free( pLeaf); if (name.Length() > 4) { nsCString ext; PRInt32 idx = name.RFindChar( '.'); if (idx != -1) { name.Right( ext, name.Length() - idx); GetMimeTypeFromExtension( ext, mimeType); } } if (mimeType.IsEmpty()) mimeType = "application/octet-stream"; aAttachmentName = name; // use the leaf name of the attachment file url as the attachment name return( NS_OK); } return( NS_ERROR_FAILURE); } PRBool nsEudoraWin32::FindMimeIniFile( nsIFileSpec *pSpec) { nsCOMPtr dir; nsresult rv = NS_NewDirectoryIterator( getter_AddRefs( dir)); if (NS_FAILED( rv)) return( PR_FALSE); PRBool exists = PR_FALSE; rv = dir->Init( pSpec, PR_TRUE); if (NS_FAILED( rv)) return( PR_FALSE); rv = dir->Exists( &exists); if (NS_FAILED( rv)) return( PR_FALSE); PRBool isFile; nsCOMPtr entry; char * pName; nsCString fName; nsCString ext; nsCString name; PRBool found = PR_FALSE; while (exists && NS_SUCCEEDED( rv)) { rv = dir->GetCurrentSpec( getter_AddRefs( entry)); if (NS_SUCCEEDED( rv)) { rv = entry->GetLeafName( &pName); if (NS_SUCCEEDED( rv) && pName) { fName = pName; nsCRT::free( pName); if (fName.Length() > 4) { fName.Right( ext, 4); fName.Left( name, fName.Length() - 4); } else { ext.Truncate(); name = fName; } ToLowerCase(ext); if (ext.EqualsLiteral(".ini")) { isFile = PR_FALSE; entry->IsFile( &isFile); if (isFile) { if (found) { // which one of these files is newer? PRUint32 modDate1, modDate2; entry->GetModDate( &modDate2); pSpec->GetModDate( &modDate1); if (modDate2 > modDate1) pSpec->FromFileSpec( entry); } else { pSpec->FromFileSpec( entry); found = PR_TRUE; } } } } } rv = dir->Next(); if (NS_SUCCEEDED( rv)) rv = dir->Exists( &exists); } if (found) return( PR_TRUE); else return( PR_FALSE); } void nsEudoraWin32::GetMimeTypeFromExtension( nsCString& ext, nsCString& mimeType) { HKEY sKey; if (::RegOpenKeyEx( HKEY_CLASSES_ROOT, ext.get(), 0, KEY_QUERY_VALUE, &sKey) == ERROR_SUCCESS) { // get the value of "Current" BYTE *pBytes = GetValueBytes( sKey, "Content Type"); if (pBytes) { mimeType = (const char *)pBytes; delete [] pBytes; } ::RegCloseKey( sKey); } if (!mimeType.IsEmpty() || !m_mailImportLocation || (ext.Length() > 10)) return; // TLR: FIXME: We should/could cache the extension to mime type maps we find // and check the cache first before scanning all of eudora's mappings? // It's not in the registry, try and find the .ini file for Eudora's private // mime type list if (!m_pMimeSection) { nsIFileSpec *pSpec; nsresult rv = NS_NewFileSpec( &pSpec); if (NS_FAILED( rv) || !pSpec) return; pSpec->FromFileSpec( m_mailImportLocation); pSpec->AppendRelativeUnixPath( "eudora.ini"); PRBool exists = PR_FALSE; PRBool isFile = PR_FALSE; rv = pSpec->Exists( &exists); if (NS_SUCCEEDED( rv)) rv = pSpec->IsFile( &isFile); if (!isFile || !exists) { rv = pSpec->FromFileSpec( m_mailImportLocation); if (NS_FAILED( rv)) return; if (!FindMimeIniFile( pSpec)) return; } char *pName = nsnull; pSpec->GetNativePath( &pName); if (!pName) return; nsCString fileName(pName); nsCRT::free( pName); // Read the mime map section DWORD size = 1024; DWORD dSize = size - 2; while (dSize == (size - 2)) { if (m_pMimeSection) delete [] m_pMimeSection; size += 1024; m_pMimeSection = new char[size]; dSize = ::GetPrivateProfileSection( "Mappings", m_pMimeSection, size, fileName.get()); } } if (!m_pMimeSection) return; IMPORT_LOG1( "Looking for mime type for extension: %s\n", ext.get()); // out/in/both=extension,mac creator,mac type,mime type1,mime type2 const char *pExt = ext.get(); pExt++; char * pChar = m_pMimeSection; char * pStart; int len; nsCString tStr; for(;;) { while (*pChar != '=') { if (!(*pChar) && !(*(pChar + 1))) return; pChar++; } if (*pChar) pChar++; pStart = pChar; len = 0; while (*pChar && (*pChar != ',')) { pChar++; len++; } if (!*pChar) return; tStr.Truncate(); tStr.Append( pStart, len); tStr.Trim( kWhitespace); if (!nsCRT::strcasecmp( tStr.get(), pExt)) { // skip the mac creator and type pChar++; while (*pChar && (*pChar != ',')) pChar++; if (!*pChar) return; pChar++; while (*pChar && (*pChar != ',')) pChar++; if (!*pChar) return; pChar++; // Get the first mime type len = 0; pStart = pChar; while (*pChar && (*pChar != ',')) { pChar++; len++; } if (!*pChar) return; pChar++; if (!len) continue; tStr.Truncate(); tStr.Append( pStart, len); tStr.Trim( kWhitespace); if (tStr.IsEmpty()) continue; mimeType.Truncate(); mimeType.Append( tStr.get()); mimeType.Append( "/"); pStart = pChar; len = 0; while (*pChar && (*pChar != 0x0D) && (*pChar != 0x0A)) { pChar++; len++; } if (!len) continue; tStr.Truncate(); tStr.Append( pStart, len); tStr.Trim( kWhitespace); if (tStr.IsEmpty()) continue; mimeType.Append( tStr.get()); IMPORT_LOG1( "Found Mime Type: %s\n", mimeType.get()); return; } } } PRBool nsEudoraWin32::FindAddressFolder( nsIFileSpec *pFolder) { IMPORT_LOG0( "*** Looking for Eudora address folder\n"); return( FindEudoraLocation( pFolder)); } nsresult nsEudoraWin32::FindAddressBooks( nsIFileSpec *pRoot, nsISupportsArray **ppArray) { nsCOMPtr spec; nsresult rv = NS_NewFileSpec( getter_AddRefs( spec)); if (NS_FAILED( rv)) return( rv); rv = spec->FromFileSpec( pRoot); if (NS_FAILED( rv)) return( rv); rv = NS_NewISupportsArray( ppArray); if (NS_FAILED( rv)) { IMPORT_LOG0( "FAILED to allocate the nsISupportsArray\n"); return( rv); } nsCOMPtr impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv)); if (NS_FAILED( rv)) return( rv); NS_IF_RELEASE( m_addressImportFolder); m_addressImportFolder = pRoot; NS_IF_ADDREF( pRoot); nsString displayName; nsEudoraStringBundle::GetStringByID( EUDORAIMPORT_NICKNAMES_NAME, displayName); // First off, get the default nndbase.txt, then scan the default nicknames subdir, // then look in the .ini file for additional directories to scan for address books! rv = spec->AppendRelativeUnixPath( "nndbase.txt"); PRBool exists = PR_FALSE; PRBool isFile = PR_FALSE; if (NS_SUCCEEDED( rv)) rv = spec->Exists( &exists); if (NS_SUCCEEDED( rv) && exists) rv = spec->IsFile( &isFile); if (exists && isFile) { if (NS_FAILED( rv = FoundAddressBook( spec, displayName.get(), *ppArray, impSvc))) return( rv); } // Try the default directory rv = spec->FromFileSpec( pRoot); if (NS_FAILED( rv)) return( rv); rv = spec->AppendRelativeUnixPath( "Nickname"); PRBool isDir = PR_FALSE; exists = PR_FALSE; if (NS_SUCCEEDED( rv)) rv = spec->Exists( &exists); if (NS_SUCCEEDED( rv) && exists) rv = spec->IsDirectory( &isDir); if (exists && isDir) { if (NS_FAILED( rv = ScanAddressDir( spec, *ppArray, impSvc))) return( rv); } // Try the ini file to find other directories! rv = spec->FromFileSpec( pRoot); if (NS_SUCCEEDED( rv)) rv = spec->AppendRelativeUnixPath( "eudora.ini"); exists = PR_FALSE; isFile = PR_FALSE; if (NS_SUCCEEDED( rv)) rv = spec->Exists( &exists); if (NS_SUCCEEDED( rv) && exists) rv = spec->IsFile( &isFile); if (!isFile || !exists) { rv = spec->FromFileSpec( pRoot); if (NS_FAILED( rv)) return( NS_OK); if (!FindMimeIniFile( spec)) return( NS_OK); } char *pName = nsnull; spec->GetNativePath( &pName); if (!pName) return( NS_OK); nsCString fileName(pName); nsCRT::free( pName); // This is the supposed ini file name! // Get the extra directories for nicknames and parse it for valid nickname directories // to look into... char *pBuffer = new char[2048]; DWORD len = ::GetPrivateProfileString( "Settings", "ExtraNicknameDirs", "", pBuffer, 2048, fileName.get()); if (len == 2047) { // If the value is really that large then don't bother! delete [] pBuffer; return( NS_OK); } nsCString dirs(pBuffer); delete [] pBuffer; dirs.Trim( kWhitespace); PRInt32 idx = 0; nsCString currentDir; while ((idx = dirs.FindChar( ';')) != -1) { dirs.Left( currentDir, idx); currentDir.Trim( kWhitespace); if (!currentDir.IsEmpty()) { rv = spec->SetNativePath( currentDir.get()); exists = PR_FALSE; isDir = PR_FALSE; if (NS_SUCCEEDED( rv)) rv = spec->Exists( &exists); if (NS_SUCCEEDED( rv) && exists) rv = spec->IsDirectory( &isDir); if (exists && isDir) { if (NS_FAILED( rv = ScanAddressDir( spec, *ppArray, impSvc))) return( rv); } } dirs.Right( currentDir, dirs.Length() - idx - 1); dirs = currentDir; dirs.Trim( kWhitespace); } if (!dirs.IsEmpty()) { rv = spec->SetNativePath( dirs.get()); exists = PR_FALSE; isDir = PR_FALSE; if (NS_SUCCEEDED( rv)) rv = spec->Exists( &exists); if (NS_SUCCEEDED( rv) && exists) rv = spec->IsDirectory( &isDir); if (exists && isDir) { if (NS_FAILED( rv = ScanAddressDir( spec, *ppArray, impSvc))) return( rv); } } return( NS_OK); } nsresult nsEudoraWin32::ScanAddressDir( nsIFileSpec *pDir, nsISupportsArray *pArray, nsIImportService *impSvc) { nsCOMPtr dir; nsresult rv = NS_NewDirectoryIterator( getter_AddRefs( dir)); if (NS_FAILED( rv)) return( rv); PRBool exists = PR_FALSE; rv = dir->Init( pDir, PR_TRUE); if (NS_FAILED( rv)) return( rv); rv = dir->Exists( &exists); if (NS_FAILED( rv)) return( rv); PRBool isFile; nsCOMPtr entry; char * pName; nsCString fName; nsCString ext; nsCString name; while (exists && NS_SUCCEEDED( rv)) { rv = dir->GetCurrentSpec( getter_AddRefs( entry)); if (NS_SUCCEEDED( rv)) { rv = entry->GetLeafName( &pName); if (NS_SUCCEEDED( rv) && pName) { fName = pName; nsCRT::free( pName); if (fName.Length() > 4) { fName.Right( ext, 4); fName.Left( name, fName.Length() - 4); } else { ext.Truncate(); name = fName; } ToLowerCase(ext); if (ext.EqualsLiteral(".txt")) { isFile = PR_FALSE; entry->IsFile( &isFile); if (isFile) { rv = FoundAddressBook( entry, nsnull, pArray, impSvc); if (NS_FAILED( rv)) return( rv); } } } } rv = dir->Next(); if (NS_SUCCEEDED( rv)) rv = dir->Exists( &exists); } return( rv); } nsresult nsEudoraWin32::FoundAddressBook( nsIFileSpec *spec, const PRUnichar *pName, nsISupportsArray *pArray, nsIImportService *impSvc) { nsCOMPtr desc; nsISupports * pInterface; nsString name; nsresult rv; if (pName) name = pName; else { char *pLeaf = nsnull; rv = spec->GetLeafName( &pLeaf); if (NS_FAILED( rv)) return( rv); if (!pLeaf) return( NS_ERROR_FAILURE); NS_CopyNativeToUnicode(nsDependentCString(pLeaf), name); nsCRT::free( pLeaf); nsString tStr; name.Right( tStr, 4); if (tStr.LowerCaseEqualsLiteral(".txt")) { name.Left( tStr, name.Length() - 4); name = tStr; } } rv = impSvc->CreateNewABDescriptor( getter_AddRefs( desc)); if (NS_SUCCEEDED( rv)) { PRUint32 sz = 0; spec->GetFileSize( &sz); desc->SetPreferredName( name.get()); desc->SetSize( sz); nsIFileSpec *pSpec = nsnull; desc->GetFileSpec( &pSpec); if (pSpec) { pSpec->FromFileSpec( spec); NS_RELEASE( pSpec); } rv = desc->QueryInterface( kISupportsIID, (void **) &pInterface); pArray->AppendElement( pInterface); pInterface->Release(); } if (NS_FAILED( rv)) { IMPORT_LOG0( "*** Error creating address book descriptor for eudora\n"); return( rv); } return( NS_OK); } void nsEudoraWin32::ConvertPath( nsCString& str) { nsCString temp; nsCString path; PRInt32 idx = 0; PRInt32 start = 0; nsCString search; idx = str.FindChar( '\\', idx); if ((idx == 2) && (str.CharAt( 1) == ':')) { str.Left( path, 3); idx++; idx = str.FindChar( '\\', idx); start = 3; if ((idx == -1) && (str.Length() > 3)) { str.Right( temp, str.Length() - start); path.Append( temp); } } WIN32_FIND_DATA findFileData; while (idx != -1) { str.Mid( temp, start, idx - start); search = path; search.Append( temp); HANDLE h = FindFirstFile( search.get(), &findFileData); if (h == INVALID_HANDLE_VALUE) return; path.Append( findFileData.cFileName); idx++; start = idx; idx = str.FindChar( '\\', idx); FindClose( h); if (idx != -1) path.Append( '\\'); else { str.Right( temp, str.Length() - start); path.Append( '\\'); path.Append( temp); } } str = path; }