pjs/mailnews/import/src/nsImportAddressBooks.cpp

991 строка
26 KiB
C++

/* -*- 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 <pp@ludusdesign.com>
*
* 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 "prthread.h"
#include "prprf.h"
#include "nscore.h"
#include "nsCOMPtr.h"
#include "nsIImportService.h"
#include "nsISupportsArray.h"
#include "nsIImportAddressBooks.h"
#include "nsIImportGeneric.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsIImportABDescriptor.h"
#include "nsIImportFieldMap.h"
#include "nsCRT.h"
#include "nsString.h"
#include "nsIURL.h"
#include "nsNetCID.h"
#include "nsIFileSpec.h"
#include "nsILocalFile.h"
#include "nsIAddrDatabase.h"
#include "nsIAddrBookSession.h"
#include "nsIRDFService.h"
#include "nsRDFCID.h"
#include "nsAbBaseCID.h"
#include "nsIAbDirectory.h"
#include "nsIAddressBook.h"
#include "nsImportStringBundle.h"
#include "nsTextFormatter.h"
#include "nsIProxyObjectManager.h"
#include "nsProxiedService.h"
#include "ImportDebug.h"
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
static NS_DEFINE_CID(kSupportsWStringCID, NS_SUPPORTS_STRING_CID);
static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
////////////////////////////////////////////////////////////////////////
PR_STATIC_CALLBACK( void) ImportAddressThread( void *stuff);
class AddressThreadData;
class nsImportGenericAddressBooks : public nsIImportGeneric
{
public:
nsImportGenericAddressBooks();
virtual ~nsImportGenericAddressBooks();
NS_DECL_ISUPPORTS
/* nsISupports GetData (in string dataId); */
NS_IMETHOD GetData(const char *dataId, nsISupports **_retval);
NS_IMETHOD SetData(const char *dataId, nsISupports *pData);
NS_IMETHOD GetStatus( const char *statusKind, PRInt32 *_retval);
/* boolean WantsProgress (); */
NS_IMETHOD WantsProgress(PRBool *_retval);
/* boolean BeginImport (in nsISupportsString successLog, in nsISupportsString errorLog, in boolean isAddrLocHome); */
NS_IMETHOD BeginImport(nsISupportsString *successLog, nsISupportsString *errorLog, PRBool isAddrLocHome, PRBool *_retval) ;
/* boolean ContinueImport (); */
NS_IMETHOD ContinueImport(PRBool *_retval);
/* long GetProgress (); */
NS_IMETHOD GetProgress(PRInt32 *_retval);
/* void CancelImport (); */
NS_IMETHOD CancelImport(void);
private:
void GetDefaultLocation( void);
void GetDefaultBooks( void);
void GetDefaultFieldMap( void);
public:
static void SetLogs( nsString& success, nsString& error, nsISupportsString *pSuccess, nsISupportsString *pError);
static void ReportError( PRUnichar *pName, nsString *pStream);
private:
nsIImportAddressBooks * m_pInterface;
nsISupportsArray * m_pBooks;
nsCOMPtr <nsIFileSpec> m_pLocation;
nsIImportFieldMap * m_pFieldMap;
PRBool m_autoFind;
PRUnichar * m_description;
PRBool m_gotLocation;
PRBool m_found;
PRBool m_userVerify;
nsISupportsString * m_pSuccessLog;
nsISupportsString * m_pErrorLog;
PRUint32 m_totalSize;
PRBool m_doImport;
AddressThreadData * m_pThreadData;
char * m_pDestinationUri;
};
class AddressThreadData {
public:
PRBool driverAlive;
PRBool threadAlive;
PRBool abort;
PRBool fatalError;
PRUint32 currentTotal;
PRUint32 currentSize;
nsISupportsArray * books;
nsIImportAddressBooks * addressImport;
nsIImportFieldMap * fieldMap;
nsISupportsString * successLog;
nsISupportsString * errorLog;
char * pDestinationUri;
PRBool bAddrLocInput ;
AddressThreadData();
~AddressThreadData();
void DriverDelete();
void ThreadDelete();
void DriverAbort();
};
nsresult NS_NewGenericAddressBooks(nsIImportGeneric** aImportGeneric)
{
NS_PRECONDITION(aImportGeneric != nsnull, "null ptr");
if (! aImportGeneric)
return NS_ERROR_NULL_POINTER;
nsImportGenericAddressBooks *pGen = new nsImportGenericAddressBooks();
if (pGen == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF( pGen);
nsresult rv = pGen->QueryInterface( NS_GET_IID(nsIImportGeneric), (void **)aImportGeneric);
NS_RELEASE( pGen);
return( rv);
}
nsImportGenericAddressBooks::nsImportGenericAddressBooks()
{
m_pInterface = nsnull;
m_pBooks = nsnull;
m_pSuccessLog = nsnull;
m_pErrorLog = nsnull;
m_totalSize = 0;
m_doImport = PR_FALSE;
m_pThreadData = nsnull;
m_pDestinationUri = nsnull;
m_pFieldMap = nsnull;
m_autoFind = PR_FALSE;
m_description = nsnull;
m_gotLocation = PR_FALSE;
m_found = PR_FALSE;
m_userVerify = PR_FALSE;
}
nsImportGenericAddressBooks::~nsImportGenericAddressBooks()
{
if (m_pThreadData) {
m_pThreadData->DriverAbort();
m_pThreadData = nsnull;
}
if (m_pDestinationUri)
nsCRT::free( m_pDestinationUri);
if (m_description)
nsCRT::free( m_description);
NS_IF_RELEASE( m_pFieldMap);
NS_IF_RELEASE( m_pInterface);
NS_IF_RELEASE( m_pBooks);
NS_IF_RELEASE( m_pSuccessLog);
NS_IF_RELEASE( m_pErrorLog);
}
NS_IMPL_THREADSAFE_ISUPPORTS1(nsImportGenericAddressBooks, nsIImportGeneric)
NS_IMETHODIMP nsImportGenericAddressBooks::GetData(const char *dataId, nsISupports **_retval)
{
NS_PRECONDITION(_retval != nsnull, "null ptr");
if (!_retval)
return NS_ERROR_NULL_POINTER;
nsresult rv;
*_retval = nsnull;
if (!nsCRT::strcasecmp( dataId, "addressInterface")) {
*_retval = m_pInterface;
NS_IF_ADDREF( m_pInterface);
}
if (!nsCRT::strcasecmp( dataId, "addressLocation")) {
if (!m_pLocation)
GetDefaultLocation();
NS_IF_ADDREF(*_retval = m_pLocation);
}
if (!nsCRT::strcasecmp( dataId, "addressBooks")) {
if (!m_pLocation)
GetDefaultLocation();
if (!m_pBooks)
GetDefaultBooks();
*_retval = m_pBooks;
NS_IF_ADDREF( m_pBooks);
}
if (!nsCRT::strcasecmp( dataId, "addressDestination")) {
if (m_pDestinationUri) {
nsCOMPtr<nsISupportsCString> abString = do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
abString->SetData(nsDependentCString(m_pDestinationUri));
NS_IF_ADDREF( *_retval = abString);
}
}
if (!nsCRT::strcasecmp( dataId, "fieldMap")) {
if (m_pFieldMap) {
*_retval = m_pFieldMap;
m_pFieldMap->AddRef();
}
else {
if (m_pInterface && m_pLocation) {
PRBool needsIt = PR_FALSE;
m_pInterface->GetNeedsFieldMap( m_pLocation, &needsIt);
if (needsIt) {
GetDefaultFieldMap();
if (m_pFieldMap) {
*_retval = m_pFieldMap;
m_pFieldMap->AddRef();
}
}
}
}
}
if (!nsCRT::strncasecmp( dataId, "sampleData-", 11)) {
// extra the record number
const char *pNum = dataId + 11;
PRInt32 rNum = 0;
while (*pNum) {
rNum *= 10;
rNum += (*pNum - '0');
pNum++;
}
IMPORT_LOG1( "Requesting sample data #: %ld\n", (long)rNum);
if (m_pInterface) {
nsCOMPtr<nsISupportsString> data = do_CreateInstance( kSupportsWStringCID, &rv);
if (NS_FAILED( rv))
return( rv);
PRUnichar * pData = nsnull;
PRBool found = PR_FALSE;
rv = m_pInterface->GetSampleData( rNum, &found, &pData);
if (NS_FAILED( rv))
return( rv);
if (found) {
data->SetData(nsDependentString(pData));
*_retval = data;
NS_ADDREF( *_retval);
}
nsCRT::free( pData);
}
}
return( NS_OK);
}
NS_IMETHODIMP nsImportGenericAddressBooks::SetData( const char *dataId, nsISupports *item)
{
NS_PRECONDITION(dataId != nsnull, "null ptr");
if (!dataId)
return NS_ERROR_NULL_POINTER;
if (!nsCRT::strcasecmp( dataId, "addressInterface")) {
NS_IF_RELEASE( m_pInterface);
if (item)
item->QueryInterface( NS_GET_IID(nsIImportAddressBooks), (void **) &m_pInterface);
}
if (!nsCRT::strcasecmp( dataId, "addressBooks")) {
NS_IF_RELEASE( m_pBooks);
if (item)
item->QueryInterface( NS_GET_IID(nsISupportsArray), (void **) &m_pBooks);
}
if (!nsCRT::strcasecmp( dataId, "addressLocation")) {
m_pLocation = nsnull;
if (item) {
nsresult rv;
nsCOMPtr <nsILocalFile> location = do_QueryInterface(item, &rv);
NS_ENSURE_SUCCESS(rv,rv);
rv = NS_NewFileSpecFromIFile(location, getter_AddRefs(m_pLocation));
NS_ENSURE_SUCCESS(rv,rv);
}
if (m_pInterface)
m_pInterface->SetSampleLocation(m_pLocation);
}
if (!nsCRT::strcasecmp( dataId, "addressDestination")) {
if (item) {
nsCOMPtr<nsISupportsCString> abString;
item->QueryInterface( NS_GET_IID(nsISupportsCString), getter_AddRefs( abString));
if (abString) {
if (m_pDestinationUri)
nsCRT::free( m_pDestinationUri);
m_pDestinationUri = nsnull;
nsCAutoString tempUri;
abString->GetData(tempUri);
m_pDestinationUri = ToNewCString(tempUri);
}
}
}
if (!nsCRT::strcasecmp( dataId, "fieldMap")) {
NS_IF_RELEASE( m_pFieldMap);
if (item)
item->QueryInterface( NS_GET_IID(nsIImportFieldMap), (void **) &m_pFieldMap);
}
return( NS_OK);
}
NS_IMETHODIMP nsImportGenericAddressBooks::GetStatus( const char *statusKind, PRInt32 *_retval)
{
NS_PRECONDITION(statusKind != nsnull, "null ptr");
NS_PRECONDITION(_retval != nsnull, "null ptr");
if (!statusKind || !_retval)
return( NS_ERROR_NULL_POINTER);
*_retval = 0;
if (!nsCRT::strcasecmp( statusKind, "isInstalled")) {
GetDefaultLocation();
*_retval = (PRInt32) m_found;
}
if (!nsCRT::strcasecmp( statusKind, "canUserSetLocation")) {
GetDefaultLocation();
*_retval = (PRInt32) m_userVerify;
}
if (!nsCRT::strcasecmp( statusKind, "autoFind")) {
GetDefaultLocation();
*_retval = (PRInt32) m_autoFind;
}
if (!nsCRT::strcasecmp( statusKind, "supportsMultiple")) {
PRBool multi = PR_FALSE;
if (m_pInterface)
m_pInterface->GetSupportsMultiple( &multi);
*_retval = (PRInt32) multi;
}
if (!nsCRT::strcasecmp( statusKind, "needsFieldMap")) {
PRBool needs = PR_FALSE;
if (m_pInterface && m_pLocation)
m_pInterface->GetNeedsFieldMap( m_pLocation, &needs);
*_retval = (PRInt32) needs;
}
return( NS_OK);
}
void nsImportGenericAddressBooks::GetDefaultLocation( void)
{
if (!m_pInterface)
return;
if ((m_pLocation && m_gotLocation) || m_autoFind)
return;
if (m_description)
nsCRT::free( m_description);
m_description = nsnull;
m_pInterface->GetAutoFind( &m_description, &m_autoFind);
m_gotLocation = PR_TRUE;
if (m_autoFind) {
m_found = PR_TRUE;
m_userVerify = PR_FALSE;
return;
}
nsIFileSpec * pLoc = nsnull;
m_pInterface->GetDefaultLocation( &pLoc, &m_found, &m_userVerify);
if (!m_pLocation)
m_pLocation = pLoc;
else {
NS_IF_RELEASE( pLoc);
}
}
void nsImportGenericAddressBooks::GetDefaultBooks( void)
{
if (!m_pInterface || m_pBooks)
return;
if (!m_pLocation && !m_autoFind)
return;
nsresult rv = m_pInterface->FindAddressBooks( m_pLocation, &m_pBooks);
if (NS_FAILED( rv)) {
IMPORT_LOG0( "*** Error: FindAddressBooks failed\n");
}
}
void nsImportGenericAddressBooks::GetDefaultFieldMap( void)
{
if (!m_pInterface || !m_pLocation)
return;
NS_IF_RELEASE( m_pFieldMap);
nsresult rv;
nsCOMPtr<nsIImportService> impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
if (NS_FAILED(rv)) {
IMPORT_LOG0( "*** Unable to get nsIImportService.\n");
return;
}
rv = impSvc->CreateNewFieldMap( &m_pFieldMap);
if (NS_FAILED( rv))
return;
PRInt32 sz = 0;
rv = m_pFieldMap->GetNumMozFields( &sz);
if (NS_SUCCEEDED( rv))
rv = m_pFieldMap->DefaultFieldMap( sz);
if (NS_SUCCEEDED( rv))
rv = m_pInterface->InitFieldMap( m_pLocation, m_pFieldMap);
if (NS_FAILED( rv)) {
IMPORT_LOG0( "*** Error: Unable to initialize field map\n");
NS_IF_RELEASE( m_pFieldMap);
}
}
NS_IMETHODIMP nsImportGenericAddressBooks::WantsProgress(PRBool *_retval)
{
NS_PRECONDITION(_retval != nsnull, "null ptr");
if (!_retval)
return NS_ERROR_NULL_POINTER;
if (m_pThreadData) {
m_pThreadData->DriverAbort();
m_pThreadData = nsnull;
}
GetDefaultLocation();
GetDefaultBooks();
PRUint32 totalSize = 0;
PRBool result = PR_FALSE;
if (m_pBooks) {
PRUint32 count = 0;
nsresult rv = m_pBooks->Count( &count);
PRUint32 i;
PRBool import;
PRUint32 size;
for (i = 0; i < count; i++) {
nsCOMPtr<nsIImportABDescriptor> book =
do_QueryElementAt(m_pBooks, i);
if (book) {
import = PR_FALSE;
size = 0;
rv = book->GetImport( &import);
if (import) {
rv = book->GetSize( &size);
result = PR_TRUE;
}
totalSize += size;
}
}
m_totalSize = totalSize;
}
m_doImport = result;
*_retval = result;
return( NS_OK);
}
void nsImportGenericAddressBooks::SetLogs( nsString& success, nsString& error, nsISupportsString *pSuccess, nsISupportsString *pError)
{
nsAutoString str;
if (pSuccess) {
pSuccess->GetData(str);
str.Append(success);
pSuccess->SetData(success);
}
if (pError) {
pError->GetData(str);
str.Append(error);
pError->SetData(error);
}
}
NS_IMETHODIMP nsImportGenericAddressBooks::BeginImport(nsISupportsString *successLog, nsISupportsString *errorLog, PRBool isAddrLocHome, PRBool *_retval)
{
NS_PRECONDITION(_retval != nsnull, "null ptr");
if (!_retval)
return NS_ERROR_NULL_POINTER;
nsString success;
nsString error;
if (!m_doImport) {
*_retval = PR_TRUE;
nsImportStringBundle::GetStringByID( IMPORT_NO_ADDRBOOKS, success);
SetLogs( success, error, successLog, errorLog);
return( NS_OK);
}
if (!m_pInterface || !m_pBooks) {
nsImportStringBundle::GetStringByID( IMPORT_ERROR_AB_NOTINITIALIZED, error);
SetLogs( success, error, successLog, errorLog);
*_retval = PR_FALSE;
return( NS_OK);
}
if (m_pThreadData) {
m_pThreadData->DriverAbort();
m_pThreadData = nsnull;
}
NS_IF_RELEASE( m_pSuccessLog);
NS_IF_RELEASE( m_pErrorLog);
m_pSuccessLog = successLog;
m_pErrorLog = errorLog;
NS_IF_ADDREF( m_pSuccessLog);
NS_IF_ADDREF( m_pErrorLog);
// kick off the thread to do the import!!!!
m_pThreadData = new AddressThreadData();
m_pThreadData->books = m_pBooks;
NS_ADDREF( m_pBooks);
m_pThreadData->addressImport = m_pInterface;
NS_ADDREF( m_pInterface);
m_pThreadData->fieldMap = m_pFieldMap;
NS_IF_ADDREF( m_pFieldMap);
m_pThreadData->errorLog = m_pErrorLog;
NS_IF_ADDREF( m_pErrorLog);
m_pThreadData->successLog = m_pSuccessLog;
NS_IF_ADDREF( m_pSuccessLog);
if (m_pDestinationUri)
m_pThreadData->pDestinationUri = nsCRT::strdup( m_pDestinationUri);
m_pThreadData->bAddrLocInput = isAddrLocHome ;
PRThread *pThread = PR_CreateThread( PR_USER_THREAD, &ImportAddressThread, m_pThreadData,
PR_PRIORITY_NORMAL,
PR_LOCAL_THREAD,
PR_UNJOINABLE_THREAD,
0);
if (!pThread) {
m_pThreadData->ThreadDelete();
m_pThreadData->DriverDelete();
m_pThreadData = nsnull;
*_retval = PR_FALSE;
nsImportStringBundle::GetStringByID( IMPORT_ERROR_AB_NOTHREAD, error);
SetLogs( success, error, successLog, errorLog);
}
else
*_retval = PR_TRUE;
return( NS_OK);
}
NS_IMETHODIMP nsImportGenericAddressBooks::ContinueImport(PRBool *_retval)
{
NS_PRECONDITION(_retval != nsnull, "null ptr");
if (!_retval)
return NS_ERROR_NULL_POINTER;
*_retval = PR_TRUE;
if (m_pThreadData) {
if (m_pThreadData->fatalError)
*_retval = PR_FALSE;
}
return( NS_OK);
}
NS_IMETHODIMP nsImportGenericAddressBooks::GetProgress(PRInt32 *_retval)
{
// This returns the progress from the the currently
// running import mail or import address book thread.
NS_PRECONDITION(_retval != nsnull, "null ptr");
if (!_retval)
return NS_ERROR_NULL_POINTER;
if (!m_pThreadData || !(m_pThreadData->threadAlive)) {
*_retval = 100;
return( NS_OK);
}
PRUint32 sz = 0;
if (m_pThreadData->currentSize && m_pInterface) {
if (NS_FAILED( m_pInterface->GetImportProgress( &sz)))
sz = 0;
}
if (m_totalSize)
*_retval = ((m_pThreadData->currentTotal + sz) * 100) / m_totalSize;
else
*_retval = 0;
// never return less than 5 so it looks like we are doing something!
if (*_retval < 5)
*_retval = 5;
// as long as the thread is alive don't return completely
// done.
if (*_retval > 99)
*_retval = 99;
return( NS_OK);
}
NS_IMETHODIMP nsImportGenericAddressBooks::CancelImport(void)
{
if (m_pThreadData) {
m_pThreadData->abort = PR_TRUE;
m_pThreadData->DriverAbort();
m_pThreadData = nsnull;
}
return( NS_OK);
}
AddressThreadData::AddressThreadData()
{
fatalError = PR_FALSE;
driverAlive = PR_TRUE;
threadAlive = PR_TRUE;
abort = PR_FALSE;
currentTotal = 0;
currentSize = 0;
books = nsnull;
addressImport = nsnull;
successLog = nsnull;
errorLog = nsnull;
pDestinationUri = nsnull;
fieldMap = nsnull;
}
AddressThreadData::~AddressThreadData()
{
if (pDestinationUri)
nsCRT::free( pDestinationUri);
NS_IF_RELEASE( books);
NS_IF_RELEASE( addressImport);
NS_IF_RELEASE( errorLog);
NS_IF_RELEASE( successLog);
NS_IF_RELEASE( fieldMap);
}
void AddressThreadData::DriverDelete( void)
{
driverAlive = PR_FALSE;
if (!driverAlive && !threadAlive)
delete this;
}
void AddressThreadData::ThreadDelete()
{
threadAlive = PR_FALSE;
if (!driverAlive && !threadAlive)
delete this;
}
void AddressThreadData::DriverAbort()
{
if (abort && !threadAlive) {
// FIXME: Do whatever is necessary to abort what has already been imported!
}
else
abort = PR_TRUE;
DriverDelete();
}
nsIAddrDatabase *GetAddressBookFromUri( const char *pUri)
{
nsIAddrDatabase * pDatabase = nsnull;
if (pUri) {
nsresult rv = NS_OK;
NS_WITH_PROXIED_SERVICE(nsIAddressBook, addressBook, NS_ADDRESSBOOK_CONTRACTID, NS_UI_THREAD_EVENTQ, &rv);
if (addressBook)
rv = addressBook->GetAbDatabaseFromURI(pUri, &pDatabase);
}
return pDatabase;
}
nsIAddrDatabase *GetAddressBook( const PRUnichar *name, PRBool makeNew)
{
nsresult rv = NS_OK;
if (!makeNew) {
// FIXME: How do I get the list of address books and look for a
// specific name. Major bogosity!
// For now, assume we didn't find anything with that name
}
IMPORT_LOG0( "In GetAddressBook\n");
nsCOMPtr<nsIProxyObjectManager> proxyMgr =
do_GetService(kProxyObjectManagerCID, &rv);
if (NS_FAILED( rv)) {
IMPORT_LOG0( "*** Error: Unable to get proxy manager\n");
return( nsnull);
}
nsIAddrDatabase * pDatabase = nsnull;
/* Get the profile directory */
nsCOMPtr<nsILocalFile> dbPath;
NS_WITH_PROXIED_SERVICE(nsIAddrBookSession, abSession, NS_ADDRBOOKSESSION_CONTRACTID, NS_UI_THREAD_EVENTQ, &rv);
if (NS_SUCCEEDED(rv))
rv = abSession->GetUserProfileDirectory(getter_AddRefs(dbPath));
if (NS_SUCCEEDED(rv)) {
// Create a new address book file - we don't care what the file
// name is, as long as it's unique
rv = dbPath->Append(NS_LITERAL_STRING("impab.mab"));
if (NS_SUCCEEDED(rv)) {
rv = dbPath->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
if (NS_SUCCEEDED(rv)) {
IMPORT_LOG0( "Getting the address database factory\n");
NS_WITH_PROXIED_SERVICE(nsIAddrDatabase, addrDBFactory, NS_ADDRDATABASE_CONTRACTID, NS_UI_THREAD_EVENTQ, &rv);
if (NS_SUCCEEDED(rv) && addrDBFactory) {
IMPORT_LOG0( "Opening the new address book\n");
rv = addrDBFactory->Open( dbPath, PR_TRUE, PR_TRUE, &pDatabase);
}
}
}
}
if (NS_FAILED(rv)) {
IMPORT_LOG0( "Failed to get the user profile directory from the address book session\n");
}
if (pDatabase) {
// We made a database, add it to the UI?!?!?!?!?!?!
// This is major bogosity again! Why doesn't the address book
// just handle this properly for me? Uggggg...
NS_WITH_PROXIED_SERVICE(nsIRDFService, rdfService, kRDFServiceCID, NS_UI_THREAD_EVENTQ, &rv);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIRDFResource> parentResource;
rv = rdfService->GetResource(NS_LITERAL_CSTRING(kAllDirectoryRoot),
getter_AddRefs(parentResource));
nsCOMPtr<nsIAbDirectory> parentDir;
/*
* TODO
* This may not be required in the future since the
* primary listeners of the nsIAbDirectory will be
* RDF directory datasource which propagates events to
* RDF Observers. In the future the RDF directory datasource
* will proxy the observers because asynchronous directory
* implementations, such as LDAP, will assert results from
* a thread other than the UI thread.
*
*/
rv = proxyMgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID( nsIAbDirectory),
parentResource, PROXY_SYNC | PROXY_ALWAYS, getter_AddRefs( parentDir));
if (parentDir)
{
nsCAutoString URI("moz-abmdbdirectory://");
nsCAutoString leafName;
rv = dbPath->GetNativeLeafName(leafName);
if (NS_FAILED(rv)) {
IMPORT_LOG0( "*** Error: Unable to get name of database file\n");
}
else {
URI.Append(leafName);
rv = parentDir->CreateDirectoryByURI(name, URI.get (), PR_FALSE);
if (NS_FAILED(rv))
IMPORT_LOG0( "*** Error: Unable to create address book directory\n");
}
}
if (NS_SUCCEEDED(rv))
IMPORT_LOG0( "Added new address book to the UI\n");
else
IMPORT_LOG0( "*** Error: An error occurred while adding the address book to the UI\n");
}
}
return( pDatabase);
}
void nsImportGenericAddressBooks::ReportError( PRUnichar *pName, nsString *pStream)
{
if (!pStream)
return;
// load the error string
PRUnichar *pFmt = nsImportStringBundle::GetStringByID( IMPORT_ERROR_GETABOOK);
PRUnichar *pText = nsTextFormatter::smprintf( pFmt, pName);
pStream->Append( pText);
nsTextFormatter::smprintf_free( pText);
nsImportStringBundle::FreeString( pFmt);
pStream->AppendWithConversion( NS_LINEBREAK);
}
PR_STATIC_CALLBACK( void) ImportAddressThread( void *stuff)
{
IMPORT_LOG0( "In Begin ImportAddressThread\n");
AddressThreadData *pData = (AddressThreadData *)stuff;
PRUint32 count = 0;
nsresult rv = pData->books->Count( &count);
PRUint32 i;
PRBool import;
PRUint32 size;
nsCOMPtr<nsIAddrDatabase> destDB( getter_AddRefs( GetAddressBookFromUri( pData->pDestinationUri)));
nsCOMPtr<nsIAddrDatabase> pDestDB;
nsString success;
nsString error;
for (i = 0; (i < count) && !(pData->abort); i++) {
nsCOMPtr<nsIImportABDescriptor> book =
do_QueryElementAt(pData->books, i);
if (book) {
import = PR_FALSE;
size = 0;
rv = book->GetImport( &import);
if (import)
rv = book->GetSize( &size);
if (size && import) {
PRUnichar *pName;
book->GetPreferredName( &pName);
if (destDB) {
pDestDB = destDB;
}
else {
pDestDB = GetAddressBook( pName, PR_TRUE);
}
nsCOMPtr<nsIAddrDatabase> proxyAddrDatabase;
rv = NS_GetProxyForObject(NS_UI_THREAD_EVENTQ,
NS_GET_IID(nsIAddrDatabase),
pDestDB,
PROXY_SYNC | PROXY_ALWAYS,
getter_AddRefs(proxyAddrDatabase));
if (NS_FAILED(rv))
return;
PRBool fatalError = PR_FALSE;
pData->currentSize = size;
if (proxyAddrDatabase) {
PRUnichar *pSuccess = nsnull;
PRUnichar *pError = nsnull;
/*
if (pData->fieldMap) {
PRInt32 sz = 0;
PRInt32 mapIndex;
PRBool active;
pData->fieldMap->GetMapSize( &sz);
IMPORT_LOG1( "**** Field Map Size: %d\n", (int) sz);
for (PRInt32 i = 0; i < sz; i++) {
pData->fieldMap->GetFieldMap( i, &mapIndex);
pData->fieldMap->GetFieldActive( i, &active);
IMPORT_LOG3( "Field map #%d: index=%d, active=%d\n", (int) i, (int) mapIndex, (int) active);
}
}
*/
rv = pData->addressImport->ImportAddressBook( book,
proxyAddrDatabase, // destination
pData->fieldMap, // fieldmap
pData->bAddrLocInput,
&pError,
&pSuccess,
&fatalError);
if (pSuccess) {
success.Append( pSuccess);
nsCRT::free( pSuccess);
}
if (pError) {
error.Append( pError);
nsCRT::free( pError);
}
}
else {
nsImportGenericAddressBooks::ReportError( pName, &error);
}
nsCRT::free( pName);
pData->currentSize = 0;
pData->currentTotal += size;
if (!proxyAddrDatabase) {
proxyAddrDatabase->Close( PR_TRUE);
}
if (fatalError) {
pData->fatalError = PR_TRUE;
break;
}
}
}
if (destDB) {
destDB->Close( PR_TRUE);
}
}
nsImportGenericAddressBooks::SetLogs( success, error, pData->successLog, pData->errorLog);
if (pData->abort || pData->fatalError) {
// FIXME: do what is necessary to get rid of what has been imported so far.
// Nothing if we went into an existing address book! Otherwise, delete
// the ones we created?
}
pData->ThreadDelete();
}