diff --git a/mailnews/addrbook/src/nsAbLDAPProcessReplicationData.cpp b/mailnews/addrbook/src/nsAbLDAPProcessReplicationData.cpp new file mode 100644 index 00000000000..91cadeee939 --- /dev/null +++ b/mailnews/addrbook/src/nsAbLDAPProcessReplicationData.cpp @@ -0,0 +1,535 @@ +/* ***** 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 + * + * + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 "nsAbLDAPProcessReplicationData.h" +#include "nsLDAP.h" +#include "nsIAbCard.h" +#include "nsIAddrBookSession.h" +#include "nsAbBaseCID.h" +#include "nsAbUtils.h" +#include "nsAbMDBCard.h" +#include "nsAbLDAPCard.h" +#include "nsFileSpec.h" +#include "nsAbLDAPProperties.h" +#include "nsAbLDAPReplicationQuery.h" +#include "nsProxiedService.h" + +NS_IMPL_ISUPPORTS2(nsAbLDAPProcessReplicationData, nsIAbLDAPProcessReplicationData, nsILDAPMessageListener) + +nsAbLDAPProcessReplicationData::nsAbLDAPProcessReplicationData() + : mState(kQueryNotStarted), + mProtocol(-1), + mCount(0), + mReplInfo(nsnull), + mInitialized(PR_FALSE), + mDBOpen(PR_FALSE) +{ + NS_INIT_ISUPPORTS(); + /* member initializers and constructor code */ +} + +nsAbLDAPProcessReplicationData::~nsAbLDAPProcessReplicationData() +{ + /* destructor code */ + if(mDBOpen && mReplicationDB) + mReplicationDB->Close(PR_FALSE); +} + +NS_IMETHODIMP nsAbLDAPProcessReplicationData::Init(nsIAbLDAPReplicationQuery *query, nsIWebProgressListener *progressListener) +{ + NS_ENSURE_ARG_POINTER(query); + + nsresult rv = NS_OK; + + mQuery = query; + + rv = mQuery->GetReplicationInfo(&mReplInfo); + if(NS_FAILED(rv)) { + mQuery = nsnull; + return rv; + } + if(!mReplInfo) { + mQuery = nsnull; + return NS_ERROR_FAILURE; + } + + mListener = progressListener; + + mInitialized = PR_TRUE; + + return rv; +} + +NS_IMETHODIMP nsAbLDAPProcessReplicationData::GetReplicationState(PRInt32 *aReplicationState) +{ + NS_ENSURE_ARG_POINTER(aReplicationState); + + *aReplicationState = mState; + return NS_OK; +} + +NS_IMETHODIMP nsAbLDAPProcessReplicationData::GetProtocolUsed(PRInt32 *aProtocolUsed) +{ + NS_ENSURE_ARG_POINTER(aProtocolUsed); + + *aProtocolUsed = mProtocol; + return NS_OK; +} + +NS_IMETHODIMP nsAbLDAPProcessReplicationData::OnLDAPInit(nsresult aStatus) +{ + if(!mInitialized) + return NS_ERROR_NOT_INITIALIZED; + + nsresult rv = NS_OK; + + // Make sure that the Init() worked properly + if(NS_FAILED(aStatus)) { + Done(PR_FALSE); + return rv; + } + + nsCOMPtr listener; + rv = NS_GetProxyForObject(NS_CURRENT_EVENTQ, + NS_GET_IID(nsILDAPMessageListener), + NS_STATIC_CAST(nsILDAPMessageListener*, this), + PROXY_SYNC | PROXY_ALWAYS, + getter_AddRefs(listener)); + if(NS_FAILED(rv)) { + Done(PR_FALSE); + return rv; + } + + nsCOMPtr operation; + rv = mQuery->GetOperation(getter_AddRefs(operation)); + if(NS_FAILED(rv)) { + Done(PR_FALSE); + return rv; + } + + nsCOMPtr connection; + rv = mQuery->GetConnection(getter_AddRefs(connection)); + if(NS_FAILED(rv)) { + Done(PR_FALSE); + return rv; + } + + rv = operation->Init(connection, listener); + if(NS_FAILED(rv)) { + Done(PR_FALSE); + return rv; + } + + // Bind + rv = operation->SimpleBind(nsnull); + if(NS_FAILED(rv)) { + Done(PR_FALSE); + return rv; + } + + return rv; +} + +NS_IMETHODIMP nsAbLDAPProcessReplicationData::OnLDAPMessage(nsILDAPMessage *aMessage) +{ + NS_ENSURE_ARG_POINTER(aMessage); + if(!mInitialized) + return NS_ERROR_NOT_INITIALIZED; + + nsresult rv = NS_OK; + + PRInt32 messageType; + rv = aMessage->GetType(&messageType); + if(NS_FAILED(rv)) { +#ifdef DEBUG_rdayal + printf("LDAP Replication : OnLDAPMessage : couldnot GetType \n"); +#endif + Done(PR_FALSE); + return rv; + } + + switch(messageType) + { + case nsILDAPMessage::RES_BIND: + rv = OnLDAPBind(aMessage); + break; + case nsILDAPMessage::RES_SEARCH_ENTRY: + rv = OnLDAPSearchEntry(aMessage); + break; + case nsILDAPMessage::RES_SEARCH_RESULT: + rv = OnLDAPSearchResult(aMessage); + default: + // for messageTypes we donot handle return NS_OK to LDAP and move ahead. + rv = NS_OK; + break; + } + + return rv; +} + +NS_IMETHODIMP nsAbLDAPProcessReplicationData::Abort() +{ + if(!mInitialized) + return NS_ERROR_NOT_INITIALIZED; + + nsresult rv = NS_OK; + + nsCOMPtr operation; + rv = mQuery->GetOperation(getter_AddRefs(operation)); + if(operation && mState != kQueryNotStarted) + { + rv = operation->Abandon(); + if(NS_SUCCEEDED(rv)) + mState = kQueryNotStarted; + } + + if(mReplicationDB && mDBOpen) { + mReplicationDB->ForceClosed(); // force close since we need to delete the file. + mDBOpen = PR_FALSE; + + // delete the unsaved replication file + if(mReplicationFile) { + rv = mReplicationFile->Remove(PR_FALSE); + if(NS_SUCCEEDED(rv)) { + // now put back the backed up replicated file if aborted + if(mBackupReplicationFile) + rv = mBackupReplicationFile->MoveTo(nsnull, mReplInfo->fileName); + } + } + } + + + Done(PR_FALSE); + + return rv; +} + +nsresult nsAbLDAPProcessReplicationData::OnLDAPBind(nsILDAPMessage *aMessage) +{ + NS_ENSURE_ARG_POINTER(aMessage); + if(!mInitialized) + return NS_ERROR_NOT_INITIALIZED; + + PRInt32 errCode; + + nsresult rv = aMessage->GetErrorCode(&errCode); + if(NS_FAILED(rv)) { + Done(PR_FALSE); + return rv; + } + + if(errCode != nsILDAPErrors::SUCCESS) { + Done(PR_FALSE); + return NS_ERROR_FAILURE; + } + + rv = CreateABForReplicatedDir(); + if(NS_FAILED(rv)) { + // donot call Done here since CreateABForReplicationDir calls it. + return rv; + } + + rv = mQuery->QueryAllEntries(); + if(NS_FAILED(rv)) { + Done(PR_FALSE); + return rv; + } + + mState = kReplicatingAll; + + if(mListener && NS_SUCCEEDED(rv)) + mListener->OnStateChange(nsnull, nsnull, nsIWebProgressListener::STATE_START, PR_TRUE); + + return rv; +} + +nsresult nsAbLDAPProcessReplicationData::OnLDAPSearchEntry(nsILDAPMessage *aMessage) +{ + NS_ENSURE_ARG_POINTER(aMessage); + if(!mInitialized) + return NS_ERROR_NOT_INITIALIZED; + // since this runs on the main thread and is single threaded, this will + // take care of entries returned by LDAP Connection thread after Abort. + if(!mReplicationDB || !mDBOpen) + return NS_ERROR_FAILURE; + + nsresult rv; + + + nsAbLDAPCard card; + + + PRBool hasSetCardProperty = PR_FALSE; + rv = MozillaLdapPropertyRelator::createCardPropertyFromLDAPMessage(aMessage, + &card, &hasSetCardProperty); + if(NS_FAILED(rv)) { + Abort(); + return rv; + } + + if(hasSetCardProperty == PR_FALSE) + { + Abort(); + return NS_ERROR_FAILURE; + } + + +#ifdef DEBUG_rdayal + nsXPIDLString firstName; + rv = card.GetFirstName(getter_Copies(firstName)); + NS_ENSURE_SUCCESS(rv,rv); + nsXPIDLString lastName; + rv = card.GetLastName(getter_Copies(lastName)); + NS_ENSURE_SUCCESS(rv,rv); + nsCAutoString name; + name.AssignWithConversion(firstName); + name.Append(" "); + name.AppendWithConversion(lastName); + printf("\n LDAPReplication :: got card #: %d, name: %s \n", mCount, name.get()); +#endif + + + nsCOMPtr dbCard; + dbCard = do_CreateInstance(NS_ABMDBCARD_CONTRACTID, &rv); + if(NS_FAILED(rv)) { + Abort(); + return rv; + } + + nsCOMPtr newCard; + newCard = do_QueryInterface(dbCard, &rv); + if(NS_FAILED(rv)) { + Abort(); + return rv; + } + + rv = newCard->Copy(&card); + if(NS_FAILED(rv)) { + Abort(); + return rv; + } + + rv = mReplicationDB->CreateNewCardAndAddToDB(newCard, PR_FALSE); + if(NS_FAILED(rv)) { + Abort(); + return rv; + } + + mCount ++; + + if(!(mCount % 10)) // inform the listener every 10 entries + { + mListener->OnProgressChange(nsnull,nsnull,mCount, -1, mCount, -1); + // in case if the LDAP Connection thread is starved and causes problem + // uncomment this one and try. + // PR_Sleep(PR_INTERVAL_NO_WAIT); // give others a chance + } + + return rv; +} + + +nsresult nsAbLDAPProcessReplicationData::OnLDAPSearchResult(nsILDAPMessage *aMessage) +{ +#ifdef DEBUG_rdayal + printf("LDAP Replication : Got Results for Completion"); +#endif + + NS_ENSURE_ARG_POINTER(aMessage); + if(!mInitialized) + return NS_ERROR_NOT_INITIALIZED; + + nsresult rv = NS_OK; + PRInt32 errorCode; + rv = aMessage->GetErrorCode(&errorCode); + + if(NS_SUCCEEDED(rv)) { + // We are done with the LDAP search for all entries. + if(errorCode == nsILDAPErrors::SUCCESS || errorCode == nsILDAPErrors::SIZELIMIT_EXCEEDED) { + Done(PR_TRUE); + if(mReplicationDB && mDBOpen) { + rv = mReplicationDB->Close(PR_TRUE); + NS_ASSERTION(NS_SUCCEEDED(rv), "Replication DB Close on Success failed"); + mDBOpen = PR_FALSE; + // once we have saved the new replication file, delete the backup file + if(mBackupReplicationFile) + { + rv = mBackupReplicationFile->Remove(PR_FALSE); + NS_ASSERTION(NS_SUCCEEDED(rv), "Replication BackupFile Remove on Success failed"); + } + } + return NS_OK; + } + } + + // in case if GetErrorCode returned error or errorCode is not SUCCESS / SIZELIMIT_EXCEEDED + if(mReplicationDB && mDBOpen) { + // if error result is returned close the DB without saving ??? + // should we commit anyway ??? whatever is returned is not lost then !! + rv = mReplicationDB->ForceClosed(); // force close since we need to delete the file. + NS_ASSERTION(NS_SUCCEEDED(rv), "Replication DB ForceClosed on Failure failed"); + mDBOpen = PR_FALSE; + // if error result is returned remove the replicated file + if(mReplicationFile) { + rv = mReplicationFile->Remove(PR_FALSE); + NS_ASSERTION(NS_SUCCEEDED(rv), "Replication File Remove on Failure failed"); + if(NS_SUCCEEDED(rv)) { + // now put back the backed up replicated file + if(mBackupReplicationFile) + { + rv = mBackupReplicationFile->MoveTo(nsnull, mReplInfo->fileName); + NS_ASSERTION(NS_SUCCEEDED(rv), "Replication Backup File Move back on Failure failed"); + } + } + } + Done(PR_FALSE); + } + + return NS_OK; +} + +nsresult nsAbLDAPProcessReplicationData::CreateABForReplicatedDir() +{ + if(!mInitialized) + return NS_ERROR_NOT_INITIALIZED; + + nsresult rv = NS_OK; + + nsCOMPtr abSession = do_GetService(NS_ADDRBOOKSESSION_CONTRACTID, &rv); + if(NS_FAILED(rv)) { + Done(PR_FALSE); + return rv; + } + + if(!mReplInfo->fileName) { + Done(PR_FALSE); + return NS_ERROR_FAILURE; + } + + nsFileSpec* dbPath; + rv = abSession->GetUserProfileDirectory(&dbPath); + if(NS_FAILED(rv)) { + Done(PR_FALSE); + return rv; + } + + (*dbPath) += mReplInfo->fileName; + + // if the AB DB already exists backup existing one, + // in case if the user cancels or Abort put back the backed up file + if(dbPath->Exists()) { + // get nsIFile for nsFileSpec from abSession, why use a obsolete class if not required! + rv = NS_FileSpecToIFile(dbPath, getter_AddRefs(mReplicationFile)); + if(NS_FAILED(rv)) { + delete dbPath; + Done(PR_FALSE); + return rv; + } + // create the backup file object same as replication file object + // we create a backup file here since we need to cleanup the existing file + // and then commit so instead of deleting existing cards we just clone the + // existing one for a much better performance. + rv = mReplicationFile->Clone(getter_AddRefs(mBackupReplicationFile)); + if(NS_FAILED(rv)) { + delete dbPath; + Done(PR_FALSE); + return rv; + } + nsCAutoString backupFile(mReplInfo->fileName); + backupFile += BACKUP_EXTENSION; + rv = mBackupReplicationFile->MoveTo(nsnull, backupFile.get()); + if (rv == NS_ERROR_FILE_ALREADY_EXISTS) + { + // create a temp nsILocalFile object for the existing backup file to delete it + nsCOMPtr existingBackupFile; + nsXPIDLCString backupFilePath; + rv = mBackupReplicationFile->GetPath(getter_Copies(backupFilePath)); + if (NS_SUCCEEDED(rv)) + { + backupFilePath += BACKUP_EXTENSION; + rv = NS_NewLocalFile(backupFilePath.get(), PR_TRUE, getter_AddRefs(existingBackupFile)); + // remove the existing backup file and move the cloned replication file to backup file + if (NS_SUCCEEDED(rv)) + { + rv = existingBackupFile->Remove(PR_FALSE); + if (NS_SUCCEEDED(rv)) + rv = mBackupReplicationFile->MoveTo(nsnull, backupFile.get()); + } + } + } + // this will take care of all failed cases for moving to backup file above + if(NS_FAILED(rv)) { + delete dbPath; + Done(PR_FALSE); + return rv; + } + } + + nsCOMPtr addrDBFactory = + do_GetService(NS_ADDRDATABASE_CONTRACTID, &rv); + if(NS_FAILED(rv)) { + delete dbPath; + Done(PR_FALSE); + return rv; + } + + rv = addrDBFactory->Open(dbPath, PR_TRUE, getter_AddRefs(mReplicationDB), PR_TRUE); + delete dbPath; + if(NS_FAILED(rv)) { + Done(PR_FALSE); + return rv; + } + + mDBOpen = PR_TRUE; // replication DB is now Open + return rv; +} + +void nsAbLDAPProcessReplicationData::Done(PRBool aSuccess) +{ + if(!mInitialized) + return; + + mQuery->Done(aSuccess); + + if(mListener) + mListener->OnStateChange(nsnull, nsnull, nsIWebProgressListener::STATE_STOP, aSuccess); + + // since this is called when all is done here, either on success, failure or abort + // releas the query now. + mQuery = nsnull; +} diff --git a/mailnews/addrbook/src/nsAbLDAPProcessReplicationData.h b/mailnews/addrbook/src/nsAbLDAPProcessReplicationData.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/mailnews/addrbook/src/nsAbLDAPReplicationQuery.cpp b/mailnews/addrbook/src/nsAbLDAPReplicationQuery.cpp new file mode 100644 index 00000000000..2e5da0b9369 --- /dev/null +++ b/mailnews/addrbook/src/nsAbLDAPReplicationQuery.cpp @@ -0,0 +1,290 @@ +/* ***** 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 + * + * + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 "nsAbLDAPReplicationQuery.h" +#include "nsAbLDAPReplicationService.h" +#include "nsAbLDAPProcessReplicationData.h" +#include "nsILDAPURL.h" +#include "nsAbBaseCID.h" +#include "nsAbLDAPProperties.h" +#include "nsProxiedService.h" +#include "nsLDAP.h" +#include "nsAbUtils.h" +#include "nsDirPrefs.h" + + +NS_IMPL_ISUPPORTS1(nsAbLDAPReplicationQuery, nsIAbLDAPReplicationQuery) + +nsAbLDAPReplicationQuery::nsAbLDAPReplicationQuery() + : mDirServer(nsnull), + mInitialized(PR_FALSE) +{ + NS_INIT_ISUPPORTS(); + /* member initializers and constructor code */ +} + +nsAbLDAPReplicationQuery::~nsAbLDAPReplicationQuery() +{ + DIR_DeleteServer(mDirServer); +} + +nsresult nsAbLDAPReplicationQuery::InitLDAPData() +{ + mDirServer = (DIR_Server *) PR_Calloc(1, sizeof(DIR_Server)); + if (!mDirServer) return NS_ERROR_NULL_POINTER; + + DIR_InitServerWithType(mDirServer, LDAPDirectory); + // since DeleteServer frees the prefName make a copy of prefName string + mDirServer->prefName = nsCRT::strdup(mDirPrefName.get()); + DIR_GetPrefsForOneServer(mDirServer, PR_FALSE, PR_FALSE); + + // this is done here to take care of the problem related to bug # 99124. + // earlier versions of Mozilla could have the fileName associated with the directory + // to be abook.mab which is the profile's personal addressbook. If the pref points to + // it generate a new filename and set it as the replication filename. + if (!nsCRT::strcasecmp(mDirServer->fileName,kPersonalAddressbook) || !mDirServer->fileName) + DIR_SetServerFileName(mDirServer, mDirServer->serverName); + // use the dir server filename for replication + PR_FREEIF(mDirServer->replInfo->fileName); + // since DeleteServer frees the replInfo->fileName make a copy of string + // if we donot do this the DeleteServer functions crashes. + mDirServer->replInfo->fileName = nsCRT::strdup(mDirServer->fileName); + + nsresult rv = NS_OK; + + mURL = do_CreateInstance(NS_LDAPURL_CONTRACTID, &rv); + if (NS_FAILED(rv)) + return rv; + + rv = mURL->SetSpec(nsDependentCString(mDirServer->uri)); + if (NS_FAILED(rv)) + return rv; + + mConnection = do_CreateInstance(NS_LDAPCONNECTION_CONTRACTID, &rv); + if (NS_FAILED(rv)) + return rv; + + mOperation = do_CreateInstance(NS_LDAPOPERATION_CONTRACTID, &rv); + if (NS_FAILED(rv)) + return rv; + + return rv; +} + +nsresult nsAbLDAPReplicationQuery::ConnectToLDAPServer(nsILDAPURL * aURL) +{ + if (!mInitialized) + return NS_ERROR_NOT_INITIALIZED; + + nsresult rv = NS_OK; + + nsCAutoString host; + rv = aURL->GetHost(host); + if (NS_FAILED(rv)) + return rv; + if (host.IsEmpty()) + return NS_ERROR_UNEXPECTED; + + PRInt32 port; + rv = aURL->GetPort(&port); + if (NS_FAILED(rv)) + return rv; + if (!port) + return NS_ERROR_UNEXPECTED; + + nsXPIDLCString dn; + rv = aURL->GetDn(getter_Copies(dn)); + if (NS_FAILED(rv)) + return rv; + if (!dn.get()) + return NS_ERROR_UNEXPECTED; + + // Initiate LDAP message listener to the current thread + nsCOMPtr listener; + rv = NS_GetProxyForObject(NS_CURRENT_EVENTQ, + NS_GET_IID(nsILDAPMessageListener), + NS_STATIC_CAST(nsILDAPMessageListener*, mDataProcessor), + PROXY_SYNC | PROXY_ALWAYS, + getter_AddRefs(listener)); + if (!listener) + return NS_ERROR_FAILURE; + + // initialize the LDAP connection + rv = mConnection->Init(host.get(), port, NS_ConvertUTF8toUCS2(dn).get(), listener); + + return rv; +} + +NS_IMETHODIMP nsAbLDAPReplicationQuery::Init(const nsACString & aPrefName, nsIWebProgressListener *aProgressListener) +{ + if (aPrefName.IsEmpty()) + return NS_ERROR_UNEXPECTED; + + mDirPrefName = aPrefName; + + nsresult rv = NS_OK; + + rv = InitLDAPData(); + if (NS_FAILED(rv)) + return rv; + + mDataProcessor = do_CreateInstance(NS_ABLDAP_PROCESSREPLICATIONDATA_CONTRACTID, &rv); + if (NS_FAILED(rv)) + return rv; + + // 'this' initialized + mInitialized = PR_TRUE; + + rv = mDataProcessor->Init(this, aProgressListener); + if (NS_FAILED(rv)) + return rv; + + return rv; +} + +NS_IMETHODIMP nsAbLDAPReplicationQuery::DoReplicationQuery() +{ + return ConnectToLDAPServer(mURL); +} + +NS_IMETHODIMP nsAbLDAPReplicationQuery::QueryAllEntries() +{ + if (!mInitialized) + return NS_ERROR_NOT_INITIALIZED; + + nsresult rv = NS_OK; + + // get the search filter associated with the directory server url; + // + nsXPIDLCString urlFilter; + rv = mURL->GetFilter(getter_Copies(urlFilter)); + if (NS_FAILED(rv)) + return rv; + + nsXPIDLCString dn; + rv = mURL->GetDn(getter_Copies(dn)); + if (NS_FAILED(rv)) + return rv; + if (!dn.get()) + return NS_ERROR_UNEXPECTED; + + PRInt32 scope; + rv = mURL->GetScope(&scope); + if (NS_FAILED(rv)) + return rv; + + CharPtrArrayGuard attributes; + rv = mURL->GetAttributes(attributes.GetSizeAddr(), attributes.GetArrayAddr()); + if (NS_FAILED(rv)) + return rv; + + rv = mOperation->SearchExt(NS_ConvertUTF8toUCS2(dn).get(), scope, + NS_ConvertUTF8toUCS2(urlFilter).get(), + attributes.GetSize(), attributes.GetArray(), + 0, 0); + return rv; +} + +NS_IMETHODIMP nsAbLDAPReplicationQuery::CancelQuery() +{ + if (!mInitialized) + return NS_ERROR_NOT_INITIALIZED; + + nsresult rv = mDataProcessor->Abort(); + return rv; +} + +NS_IMETHODIMP nsAbLDAPReplicationQuery::Done(PRBool aSuccess) +{ + if (!mInitialized) + return NS_ERROR_NOT_INITIALIZED; + + nsresult rv = NS_OK; + nsCOMPtr replicationService = + do_GetService(NS_ABLDAP_REPLICATIONSERVICE_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv)) + replicationService->Done(aSuccess); + + return rv; +} + + +NS_IMETHODIMP nsAbLDAPReplicationQuery::GetOperation(nsILDAPOperation * *aOperation) +{ + NS_ENSURE_ARG_POINTER(aOperation); + if (!mInitialized) + return NS_ERROR_NOT_INITIALIZED; + + NS_IF_ADDREF(*aOperation = mOperation); + + return NS_OK; +} + +NS_IMETHODIMP nsAbLDAPReplicationQuery::GetConnection(nsILDAPConnection * *aConnection) +{ + NS_ENSURE_ARG_POINTER(aConnection); + if (!mInitialized) + return NS_ERROR_NOT_INITIALIZED; + + NS_IF_ADDREF(*aConnection = mConnection); + + return NS_OK; +} + +NS_IMETHODIMP nsAbLDAPReplicationQuery::GetReplicationURL(nsILDAPURL * *aReplicationURL) +{ + NS_ENSURE_ARG_POINTER(aReplicationURL); + if (!mInitialized) + return NS_ERROR_NOT_INITIALIZED; + + NS_IF_ADDREF(*aReplicationURL = mURL); + + return NS_OK; +} + +NS_IMETHODIMP nsAbLDAPReplicationQuery::GetReplicationInfo(DIR_ReplicationInfo * *aReplicationInfo) +{ + NS_ENSURE_ARG_POINTER(aReplicationInfo); + if (!mInitialized) + return NS_ERROR_NOT_INITIALIZED; + + *aReplicationInfo = mDirServer->replInfo; + + return NS_OK; +} diff --git a/mailnews/addrbook/src/nsAbLDAPReplicationQuery.h b/mailnews/addrbook/src/nsAbLDAPReplicationQuery.h new file mode 100644 index 00000000000..12ff243eece --- /dev/null +++ b/mailnews/addrbook/src/nsAbLDAPReplicationQuery.h @@ -0,0 +1,77 @@ +/* ***** 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 + * + * + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 ***** */ + + +#ifndef nsAbLDAPReplicationQuery_h__ +#define nsAbLDAPReplicationQuery_h__ + +#include "nsIWebProgressListener.h" +#include "nsIAbLDAPReplicationQuery.h" +#include "nsIAbLDAPProcessReplicationData.h" +#include "nsILDAPConnection.h" +#include "nsILDAPOperation.h" +#include "nsILDAPURL.h" +#include "nsDirPrefs.h" +#include "nsString.h" + +class nsAbLDAPReplicationQuery : public nsIAbLDAPReplicationQuery +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIABLDAPREPLICATIONQUERY + + nsAbLDAPReplicationQuery(); + virtual ~nsAbLDAPReplicationQuery(); + + nsresult InitLDAPData(); + nsresult ConnectToLDAPServer(nsILDAPURL * aURL); + +protected : + // pointer to interfaces used by this object + nsCOMPtr mConnection; + nsCOMPtr mOperation; + nsCOMPtr mURL; + + nsCOMPtr mDataProcessor; + + PRBool mInitialized; + nsCString mDirPrefName; + DIR_Server * mDirServer; + +}; + +#endif // nsAbLDAPReplicationQuery_h__ diff --git a/mailnews/addrbook/src/nsAbLDAPReplicationService.cpp b/mailnews/addrbook/src/nsAbLDAPReplicationService.cpp new file mode 100644 index 00000000000..a41b894039d --- /dev/null +++ b/mailnews/addrbook/src/nsAbLDAPReplicationService.cpp @@ -0,0 +1,146 @@ +/* ***** 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 + * + * + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 "nsAbLDAPReplicationService.h" +#include "nsAbLDAPReplicationQuery.h" +#include "nsAbBaseCID.h" +#include "nsIWebProgressListener.h" + +/*** implementation of the service ******/ + +NS_IMPL_THREADSAFE_ISUPPORTS1(nsAbLDAPReplicationService, nsIAbLDAPReplicationService) + +nsAbLDAPReplicationService::nsAbLDAPReplicationService() + : mReplicating(PR_FALSE) +{ + NS_INIT_ISUPPORTS(); +} + +nsAbLDAPReplicationService::~nsAbLDAPReplicationService() +{ +} + +/* void startReplication(in string aURI, in nsIWebProgressListener progressListener); */ +NS_IMETHODIMP nsAbLDAPReplicationService::StartReplication(const nsACString & aPrefName, nsIWebProgressListener *progressListener) +{ + if(aPrefName.IsEmpty()) + return NS_ERROR_UNEXPECTED; + +#ifdef DEBUG_rdayal + printf("Start Replication called"); +#endif + + // makes sure to allow only one replication at a time + if(mReplicating) + return NS_ERROR_FAILURE; + + mPrefName = aPrefName; + + nsresult rv = NS_ERROR_NOT_IMPLEMENTED; + + switch(DecideProtocol()) + { + case nsIAbLDAPProcessReplicationData::kDefaultDownloadAll : + mQuery = do_CreateInstance(NS_ABLDAP_REPLICATIONQUERY_CONTRACTID, &rv); + if(NS_SUCCEEDED(rv) && mQuery) + { + rv = mQuery->Init(aPrefName, progressListener); + if(NS_SUCCEEDED(rv)) + { + rv = mQuery->DoReplicationQuery(); + if(NS_SUCCEEDED(rv)) + { + mReplicating = PR_TRUE; + return rv; + } + } + } + break; + default : + break; + } + + // this should come here only in case of an error, either when DoReplicationQuery errors out + // of if DecideProtocol returns an error. + if(progressListener && NS_FAILED(rv)) + progressListener->OnStateChange(nsnull, nsnull, nsIWebProgressListener::STATE_STOP, PR_FALSE); + + return rv; +} + +/* void cancelReplication(in string aURI); */ +NS_IMETHODIMP nsAbLDAPReplicationService::CancelReplication(const nsACString & aPrefName) +{ + if(aPrefName.IsEmpty()) + return NS_ERROR_UNEXPECTED; + + nsresult rv = NS_ERROR_FAILURE; + + if(aPrefName == mPrefName) + { + if(mQuery && mReplicating) + rv = mQuery->CancelQuery(); + } + + // if query has been cancelled successfully + if(NS_SUCCEEDED(rv)) + Done(PR_FALSE); + + return rv; +} + +NS_IMETHODIMP nsAbLDAPReplicationService::Done(PRBool aSuccess) +{ + mReplicating = PR_FALSE; + if(mQuery) + mQuery = nsnull; // release query obj + + return NS_OK; +} + + +// This method should query the RootDSE for the changeLog attribute, +// if it exists ChangeLog protocol is supported. +PRInt32 nsAbLDAPReplicationService::DecideProtocol() +{ + // currently only Replicate All is implemented + return nsIAbLDAPProcessReplicationData::kDefaultDownloadAll; +} + + diff --git a/mailnews/addrbook/src/nsAbLDAPReplicationService.h b/mailnews/addrbook/src/nsAbLDAPReplicationService.h new file mode 100644 index 00000000000..09bd0949576 --- /dev/null +++ b/mailnews/addrbook/src/nsAbLDAPReplicationService.h @@ -0,0 +1,66 @@ +/* ***** 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 + * + * + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 ***** */ + + + +#ifndef nsAbLDAPReplicationService_h___ +#define nsAbLDAPReplicationService_h___ + +#include "nsIAbLDAPReplicationService.h" +#include "nsIAbLDAPReplicationQuery.h" +#include "nsString.h" + +class nsAbLDAPReplicationService : public nsIAbLDAPReplicationService +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIABLDAPREPLICATIONSERVICE + + nsAbLDAPReplicationService(); + virtual ~nsAbLDAPReplicationService(); + + PRInt32 DecideProtocol(); + +protected: + nsCOMPtr mQuery; + PRBool mReplicating; + nsCString mPrefName; + +}; + + +#endif /* nsAbLDAPReplicationService_h___ */