/* ***** 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) 2002 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Rajiv Dayal * * 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 #include "syncmgr.h" #include #include #include #include #include "CondAPI.h" #include "hslog.h" #include "MozABConduitSync.h" #include "MozABConduitRecord.h" #define MAX_PROD_ID_TEXT 255 #define PERSONAL "Personal" // Global var FILE *gFD = NULL; // logging. CMozABConduitSync::CMozABConduitSync(CSyncProperties& rProps) { m_dbHH = NULL; m_dbPC = NULL; m_remoteDB = NULL; m_TotRemoteDBs = rProps.m_nRemoteCount; // Fixed 3/25/99 KRM m_ConduitHandle = (CONDHANDLE)0; memcpy(&m_rSyncProperties, &rProps, sizeof(m_rSyncProperties)); memset(&m_SystemInfo, 0, sizeof(m_SystemInfo)); // See if logging is turned on (ie, check env variable "MOZ_CONDUIT_LOG" // for a logfile like "c:\\temp\\conduitlog.txt"). char *envVar = getenv(ENV_VAR_CONDUTI_LOG); if(envVar != NULL ) gFD = fopen(envVar, "a+"); } CMozABConduitSync::~CMozABConduitSync() { long retval; if (m_SystemInfo.m_ProductIdText) { delete m_SystemInfo.m_ProductIdText; m_SystemInfo.m_ProductIdText = NULL; m_SystemInfo.m_AllocedLen = 0; } if ((!m_rSyncProperties.m_RemoteDbList) && (m_remoteDB)) { delete m_remoteDB; m_remoteDB = NULL; } if (m_ConduitHandle) { retval = SyncUnRegisterConduit(m_ConduitHandle); m_ConduitHandle = 0; } if (gFD) fclose(gFD); } long CMozABConduitSync::Perform(void) { long retval = 0; // Log the start time. time_t ltime; time( <ime ); CONDUIT_LOG1(gFD, "\n------------ START OF PALM SYNC ------------ at %s", ctime(<ime)); if (m_rSyncProperties.m_SyncType > eProfileInstall) return GEN_ERR_BAD_SYNC_TYPE; if (m_rSyncProperties.m_SyncType == eDoNothing) { return 0; } // Obtain System Information m_SystemInfo.m_ProductIdText = (BYTE*) new char [MAX_PROD_ID_TEXT]; //deleted in d'ctor if (!m_SystemInfo.m_ProductIdText) return GEN_ERR_LOW_MEMORY; m_SystemInfo.m_AllocedLen = (BYTE) MAX_PROD_ID_TEXT; retval = SyncReadSystemInfo(m_SystemInfo); if (retval) return retval; // Register this conduit with SyncMgr.DLL for communication to HH retval = SyncRegisterConduit(m_ConduitHandle); if (retval) { CONDUIT_LOG0(gFD, "Failed SyncRegisterConduit.\n"); return retval; } for (int iCount=0; iCount < m_TotRemoteDBs && !retval; iCount++) { retval = GetRemoteDBInfo(iCount); if (retval) { retval = 0; break; } m_dbHH = new MozABHHManager(GENERIC_FLAG_APPINFO_SUPPORTED | GENERIC_FLAG_CATEGORY_SUPPORTED, m_remoteDB->m_Name, m_remoteDB->m_Creator, m_remoteDB->m_DbType, m_remoteDB->m_DbFlags, 0, m_remoteDB->m_CardNum, m_rSyncProperties.m_SyncType); if(!m_dbHH) { CONDUIT_LOG0(gFD, "Failed dbHH.\n"); return GEN_ERR_LOW_MEMORY; } m_dbPC = new MozABPCManager(); if(!m_dbPC) { if (m_dbHH) delete m_dbHH; m_dbHH = NULL; CONDUIT_LOG0(gFD, "Failed dbPC.\n"); return GEN_ERR_LOW_MEMORY; } char conduitName[32]; GetConduitName(conduitName, 32); LogAddFormattedEntry(slSyncStarted, FALSE, "SYNC %s", conduitName); CONDUIT_LOG1(gFD, "slSyncStarted. SyncType=%d\n", m_rSyncProperties.m_SyncType); switch (m_rSyncProperties.m_SyncType) { case eFast: retval = PerformFastSync(); if ((retval) && (retval == GEN_ERR_CHANGE_SYNC_MODE)){ if (m_rSyncProperties.m_SyncType == eHHtoPC) retval = CopyHHtoPC(); else if (m_rSyncProperties.m_SyncType == ePCtoHH) retval = CopyPCtoHH(); } break; case eSlow: retval = PerformSlowSync(); if ((retval) && (retval == GEN_ERR_CHANGE_SYNC_MODE)){ if (m_rSyncProperties.m_SyncType == eHHtoPC) retval = CopyHHtoPC(); else if (m_rSyncProperties.m_SyncType == ePCtoHH) retval = CopyPCtoHH(); } break; case eHHtoPC: case eBackup: retval = CopyHHtoPC(); break; case eInstall: case ePCtoHH: case eProfileInstall: retval = CopyPCtoHH(); break; case eDoNothing: break; default: retval = GEN_ERR_SYNC_TYPE_NOT_SUPPORTED; break; } if (retval) { LogAddFormattedEntry(slSyncAborted, FALSE, "retval=%d %s\n", retval, conduitName); CONDUIT_LOG1(gFD, "Sync finished with errors retval=%d\n", retval); } else { LogAddFormattedEntry(slSyncFinished, FALSE, "%s", conduitName); CONDUIT_LOG0(gFD, "Sync Finished retval=0\n"); } // remove the handheld and PC manager if (m_dbHH) delete m_dbHH; m_dbHH = NULL; if (m_dbPC) delete m_dbPC; m_dbPC = NULL; } // Log the end time. time( <ime ); CONDUIT_LOG1(gFD, "------------ END OF PALM SYNC -------------- at %s\n", ctime(<ime)); // Unregister the conduit long retval2 = 0; if (m_ConduitHandle) { retval2 = SyncUnRegisterConduit(m_ConduitHandle); m_ConduitHandle = 0; } if (!retval) return retval2; return retval; } long CMozABConduitSync::GetRemoteDBInfo(int iIndex) { long retval = 0; if (m_rSyncProperties.m_RemoteDbList) { m_remoteDB = m_rSyncProperties.m_RemoteDbList[iIndex]; } else { if (m_remoteDB) delete m_remoteDB; m_remoteDB = new CDbList; // deleted in d'ctor if (m_remoteDB) { m_remoteDB->m_Creator = m_rSyncProperties.m_Creator; m_remoteDB->m_DbFlags = eRecord; // todo m_remoteDB->m_DbType = m_rSyncProperties.m_DbType; strncpy(m_remoteDB->m_Name, m_rSyncProperties.m_RemoteName[iIndex], sizeof(m_remoteDB->m_Name)-1); m_remoteDB->m_Name[sizeof(m_remoteDB->m_Name)-1] = '\0'; m_remoteDB->m_Version = 0; m_remoteDB->m_CardNum = 0; m_remoteDB->m_ModNumber = 0; m_remoteDB->m_CreateDate= 0; m_remoteDB->m_ModDate = 0; m_remoteDB->m_BackupDate= 0; } else { retval = GEN_ERR_LOW_MEMORY; } } return retval; } BOOL CMozABConduitSync::CategoryNameMatches(CPString &catName, CPString &cutOffMozABName, BOOL isPAB) { if (!catName.CompareNoCase(cutOffMozABName.GetBuffer(0))) return TRUE; else return (isPAB && !catName.CompareNoCase("Personal")); } BOOL CMozABConduitSync::CategoryExists(CPString &mozABName, BOOL isPAB) { CPCategory * pCategory = m_dbHH->GetFirstCategory(); // Palm only allows 15 chars for category names. CPString cutOffName; if (mozABName.Length() > 15) cutOffName = mozABName.Left(15); else cutOffName = mozABName; while (pCategory) { CPString catName(pCategory->GetName()); if (CategoryNameMatches(catName, cutOffName, isPAB)) return TRUE; // Process next category pCategory = m_dbHH->GetNextCategory(); } return FALSE; } // this is done in separate thread since the main thread in this DLL // needs to call SyncYieldCycles(1) atleast once every 7 seconds DWORD WINAPI DoFastSync(LPVOID lpParameter) { CONDUIT_LOG0(gFD, "-- SYNC DoFastSync --\n"); CMozABConduitSync * sync = (CMozABConduitSync * ) lpParameter; if(!sync || !sync->m_dbHH) return 0; BOOL initialHHSync = (sync->m_rSyncProperties.m_FirstDevice == eHH); if (initialHHSync) // if HH has been reset, copy everything on pc to hh. return sync->CopyPCtoHH(); long retval=0; BOOL success = FALSE; DWORD mozABCount=0; LONG * mozCatIndexList = NULL; // freed by MSCOM/Mozilla CPString ** mozABNameList = NULL; // freed by MSCOM/Mozilla CPString ** mozABUrlList = NULL; // freed by MSCOM/Mozilla BOOL * mozDirFlagsList = NULL; // freed by MSCOM/Mozilla BOOL neverDidPalmSyncBefore = TRUE; // 1st time palm sync? DWORD mozABIndex; retval = sync->m_dbHH->OpenDB(FALSE); if (!retval) retval = sync->m_dbHH->LoadCategories(); CONDUIT_LOG0(gFD, "Getting moz AB List ... "); if(!retval) retval = sync->m_dbPC->GetPCABList(&mozABCount, &mozCatIndexList, &mozABNameList, &mozABUrlList, &mozDirFlagsList); CONDUIT_LOG1(gFD, "done getting moz AB List. retval = %d\n", retval); if (retval) return retval; // Create an array to help us identify addrbooks that have been deleted on Palm. DWORD *mozABSeen = (DWORD *) CoTaskMemAlloc(sizeof(DWORD) * mozABCount); if (!mozABSeen) return GEN_ERR_LOW_MEMORY; else memset(mozABSeen, FALSE, sizeof(DWORD) * mozABCount); CONDUIT_LOG1(gFD, "first device = %lx\n", sync->m_rSyncProperties.m_FirstDevice); // See if palm sync was performed before. for(mozABIndex=0; mozABIndexGetBuffer(0), mozABUrlList[mozABIndex]->GetBuffer(0)); } // For each category, try to find the corresponding AB in the moz AB list // and see if it has been synchronized before and take action accordingly. CPCategory * pCategory = sync->m_dbHH->GetFirstCategory(); while (pCategory) { CPalmRecord ** recordListHH = NULL; DWORD recordCountHH=0; DWORD catID = pCategory->GetID(); DWORD catIndex = pCategory->GetIndex(); DWORD catFlags = pCategory->GetFlags(); CPString catName(pCategory->GetName()); CONDUIT_LOG3(gFD, "\nProcessing Palm AB '%s' (catIndex/catId) = (%d/%d)... \n", catName.GetBuffer(0), catIndex, catID); BOOL abRenamed = FALSE; BOOL foundInABList=FALSE; for(mozABIndex=0; mozABIndexLength() > 15) cutOffName = mozABNameList[mozABIndex]->Left(15); else cutOffName = *mozABNameList[mozABIndex]; // if this category has been synchronized before if(catIndex == mozCatIndexList[mozABIndex]) { retval = sync->m_dbHH->LoadUpdatedRecordsInCategory(catIndex, &recordListHH, &recordCountHH); CONDUIT_LOG2(gFD, "Category index = %d, name = '%s' has been synced before\n", catID, catName.GetBuffer(0)); foundInABList = TRUE; mozABSeen[mozABIndex] = TRUE; // mark it seen // See if the name has been changed on Palm side. Note that if both // Palm category and the corresponding moz addrbook are renamed then // Palm category name takes precedence. if (!sync->CategoryNameMatches(catName, cutOffName, mozDirFlagsList[mozABIndex] & kIsPabDirFlag)) { abRenamed = TRUE; CONDUIT_LOG3(gFD, "Category index = %d, name = '%s' was renamed (from '%s') on Palm so do the same on moz\n", catID, catName.GetBuffer(0), mozABNameList[mozABIndex]->GetBuffer(0)); } break; } // if corresponding category exists but not synchronized before if(sync->CategoryNameMatches(catName, cutOffName, mozDirFlagsList[mozABIndex] & kIsPabDirFlag)) { retval = sync->m_dbHH->LoadAllRecordsInCategory(catIndex, &recordListHH, &recordCountHH); CONDUIT_LOG2(gFD, "Category index = %d, name = '%s' has not been synced before\n", catID, catName.GetBuffer(0)); foundInABList = TRUE; mozABSeen[mozABIndex] = TRUE; // mark it seen break; } } // end of for if(!retval && foundInABList) { CPalmRecord ** recordListPC=NULL; DWORD recordCountPC=0; DWORD newRecAddedCount = 0; DWORD * newRecIDList=NULL; CONDUIT_LOG1(gFD, " Syncing with moz AB with %d modified Palm record(s) ... ", recordCountHH); retval = sync->m_dbPC->SynchronizePCAB(catIndex, catID, catName, recordCountHH, recordListHH, &recordCountPC, &recordListPC); CONDUIT_LOG1(gFD, "Done syncing AB. retval=%lx.\n", retval); // SynchronizePCAB() returns a list of modified moz records so update those on Palm. if (!retval) { unsigned long i; newRecIDList = (DWORD *) calloc(recordCountPC, sizeof(DWORD)); if (recordCountPC > 0) CONDUIT_LOG1(gFD, " Updating Palm AB with %d modified moz record(s) ...\n", recordCountPC); for (i=0; i < recordCountPC; i++) { if(!recordListPC[i]) continue; CPalmRecord palmRec = *recordListPC[i]; palmRec.SetCategory(catIndex); if(palmRec.GetAttribs() == ATTR_DELETED) { CONDUIT_LOG0(gFD, " - deleting a record\n"); retval = sync->m_dbHH->DeleteARecord(palmRec); } else if(palmRec.GetAttribs() == ATTR_MODIFIED) { CONDUIT_LOG0(gFD, " - modifying a record\n"); retval = sync->m_dbHH->UpdateARecord(palmRec); } else if(palmRec.GetAttribs() == ATTR_NEW) { CONDUIT_LOG0(gFD, " - adding a record\n"); retval = sync->m_dbHH->AddARecord(palmRec); // should we check existing recs? if(!retval && (newRecAddedCount < recordCountPC)) { newRecIDList[newRecAddedCount] = palmRec.GetID(); newRecAddedCount++; } } delete recordListPC[i]; // once done with PC record, delete } if (recordCountPC > 0) CONDUIT_LOG0(gFD, " Done updating Palm AB.\n"); } // the MozAB is now synchronized if(!retval) mozDirFlagsList[mozABIndex] &= ~kFirstTimeSyncDirFlag; // delete the PC recordList now that palm is updated if(recordListPC) free(recordListPC); // notify Mozilla that sync is done so that memory can be freed success = retval ? FALSE : TRUE; if(newRecAddedCount) { if(newRecAddedCount != recordCountPC) newRecIDList = (DWORD *) realloc(newRecIDList, newRecAddedCount); retval = sync->m_dbPC->NotifySyncDone(success, catIndex, newRecAddedCount, newRecIDList); } else retval = sync->m_dbPC->NotifySyncDone(success); if(newRecIDList) free(newRecIDList); // See if it was renamed on palm. if (abRenamed) { // We should not rename personal and collected address books here. if (! (mozDirFlagsList[mozABIndex] & kIsPabDirFlag) && mozABUrlList[mozABIndex]->CompareNoCase(COLLECTED_ADDRBOOK_URL)) { CONDUIT_LOG0(gFD, " Renaming AB ... "); retval = sync->m_dbPC->RenamePCAB(catIndex, catName, *mozABUrlList[mozABIndex]); CONDUIT_LOG1(gFD, "Done renaming AB. retval=%d.\n", retval); } } } // If this category can't be found in the moz AB list then two cases here: // 1. If catFlags is not CAT_DIRTY then this category has been deleted // on moz so remove it from palm side. // 2. else, if we never did palm sync on moz before then it's a new one // on palm. So create a new AB in moz with all records in this category // (even if it's an empty AB). if(!retval && !foundInABList) { if (catFlags != CAT_DIRTY && !neverDidPalmSyncBefore && !initialHHSync) { BOOL abDeleted = sync->m_dbPC->PCABDeleted(catName); if (abDeleted) { CONDUIT_LOG2(gFD, "Category index = %d, name = '%s' is removed from moz and needs to be removed from palm\n", catID, catName.GetBuffer(0)); CONDUIT_LOG0(gFD, " Deleting AB from Palm ... "); retval = sync->m_dbHH->DeleteCategory(catIndex, FALSE); CONDUIT_LOG1(gFD, "Done deleting AB from Palm. retval=%d.\n", retval); } } else { CONDUIT_LOG2(gFD, "Category index = %d, name = '%s' is new on palm and needs to be added to moz\n", catID, catName.GetBuffer(0)); retval = sync->m_dbHH->LoadAllRecordsInCategory(catIndex, &recordListHH, &recordCountHH); CONDUIT_LOG1(gFD, " Creating new moz AB with %d Palm record(s) ... ", recordCountHH); if(!retval) retval = sync->m_dbPC->AddRecords(FALSE, catIndex, catName, recordCountHH, recordListHH); CONDUIT_LOG1(gFD, "Done creating new moz AB. retval=%d.\n", retval); } } // delete and free HH records and recordList once synced if(recordListHH) { CPalmRecord ** tempRecordListHH = recordListHH; for(DWORD i=0; i < recordCountHH; i++) { if(*tempRecordListHH) delete *tempRecordListHH; tempRecordListHH++; } free(recordListHH); } // Process next category pCategory = sync->m_dbHH->GetNextCategory(); } // end of while // Deal with any Moz AB not existing in Palm, ones not sync'ed above, // and the case where Palm ABs have been deleted. for(mozABIndex=0; mozABIndexCategoryExists(*mozABNameList[mozABIndex], mozDirFlagsList[mozABIndex] & kIsPabDirFlag)) { CONDUIT_LOG3(gFD, "\nMoz AB[%d] category index = %d, name = '%s' doesn't exist on Palm so needs to be added to palm\n", mozABIndex, mozCatIndexList[mozABIndex], mozABNameList[mozABIndex]->GetBuffer(0)); CPalmRecord ** recordListPC=NULL; DWORD recordCountPC=0; DWORD * newRecIDList=NULL; CPCategory cat; retval = sync->m_dbPC->LoadAllRecords(*mozABNameList[mozABIndex], &recordCountPC, &recordListPC); if(!retval) { if (! (mozDirFlagsList[mozABIndex] & kIsPabDirFlag)) cat.SetName(mozABNameList[mozABIndex]->GetBuffer(0)); else cat.SetName("Personal"); CONDUIT_LOG1(gFD, " Creating new Palm AB with %d record(s) ... ", recordCountPC); retval = sync->m_dbHH->AddCategory(cat); CONDUIT_LOG2(gFD, "Done creating new Palm AB, new category index=%d. retval=%d.\n", cat.GetIndex(), retval); if(!retval) { CONDUIT_LOG1(gFD, " Adding %d record(s) to new Palm AB ... ", recordCountPC); newRecIDList = (DWORD *) calloc(recordCountPC, sizeof(DWORD)); for (unsigned long i=0; i < recordCountPC; i++) { if(!recordListPC[i]) continue; CPalmRecord palmRec = *recordListPC[i]; palmRec.SetCategory(cat.GetIndex()); retval = sync->m_dbHH->AddARecord(palmRec); // should we check existing recs? newRecIDList[i] = palmRec.GetID(); delete recordListPC[i]; // delete the record now that it is used } CONDUIT_LOG0(gFD, "Done adding new records to new Palm AB.\n"); } else CONDUIT_LOG1(gFD, "Creating new Palm AB failed. retval=%d.\n", retval); } else CONDUIT_LOG1(gFD, " Loading moz AB records failed so can't create new Palm AB. retval=%d.\n", retval); // the MozAB is now synchronized if(!retval) mozDirFlagsList[mozABIndex] &= ~kFirstTimeSyncDirFlag; // delete the recordList now that palm is updated if(recordListPC) free(recordListPC); // notify Mozilla that sync is done so that memory can be freed if(!retval) success = TRUE; else { success = FALSE; recordCountPC=0; } retval = sync->m_dbPC->NotifySyncDone(success, cat.GetIndex(), recordCountPC, newRecIDList); if(newRecIDList) free(newRecIDList); // Lastly, update the AB with new category index and mod time. retval = sync->m_dbPC->UpdatePCABSyncInfo(success ? cat.GetIndex() : -1, *mozABNameList[mozABIndex]); } else if (!mozABSeen[mozABIndex] && !neverDidPalmSyncBefore && !initialHHSync) { // We should not delete personal and collected address books here. Rather, // reset the mod time so next time we can sync them back to Palm again. // Note: make sure the moz addrbook has been synced before to avoid the case // where early sync failed and we delete this un-synced addrbook by mistake. if (mozCatIndexList[mozABIndex] > -1 && ! (mozDirFlagsList[mozABIndex] & kIsPabDirFlag) && mozABUrlList[mozABIndex]->CompareNoCase(COLLECTED_ADDRBOOK_URL)) { CONDUIT_LOG3(gFD, "\nMoz AB[%d] category index = %d, name = '%s' is removed on Palm and needs to be removed from moz\n", mozABIndex, mozCatIndexList[mozABIndex], mozABNameList[mozABIndex]->GetBuffer(0)); CONDUIT_LOG0(gFD, " Deleting AB from moz ... "); retval = sync->m_dbPC->DeletePCAB(mozCatIndexList[mozABIndex], *mozABNameList[mozABIndex], *mozABUrlList[mozABIndex]); CONDUIT_LOG1(gFD, "Done deleting AB from moz. retval=%d.\n", retval); } else { CONDUIT_LOG3(gFD, "\nMoz AB[%d] category index = %d, name = '%s', is removed on Palm but only need to reset sync info on moz\n", mozABIndex, mozCatIndexList[mozABIndex], mozABNameList[mozABIndex]->GetBuffer(0)); // Reset category index and mod time. CONDUIT_LOG0(gFD, " Resetting AB info on moz ... "); retval = sync->m_dbPC->UpdatePCABSyncInfo(-1, *mozABNameList[mozABIndex]); CONDUIT_LOG1(gFD, " Done resetting AB info on moz. retval=%d.\n", retval); } } } // end of mozAB not existing in Palm for loop // Purge deleted Palm record permanently (in case they were logically deleted). sync->m_dbHH->PurgeDeletedRecs(); // Free stuff we allocated. CoTaskMemFree(mozABSeen); // update category info in HH sync->m_dbHH->CompactCategoriesToHH(); // close the HH DB once synced retval = sync->m_dbHH->CloseDB(FALSE); return retval; } long CMozABConduitSync::PerformFastSync() { CONDUIT_LOG0(gFD, "-- SYNC Palm -> PerformFastSync --\n"); DWORD ThreadId; DWORD threadExitCode; HANDLE hThread = CreateThread(NULL, 0, DoFastSync, this, 0, &ThreadId); while (WaitForSingleObject(hThread, 1000) == WAIT_TIMEOUT) { SyncYieldCycles(1); // every sec call this for feedback & keep Palm connection alive continue; } // get and return thread's return code if available BOOL ret = GetExitCodeThread(hThread, &threadExitCode); if (!ret) return GetLastError(); // thread failed CONDUIT_LOG1(gFD, "GetExitCodeThread failed return code = %d\n", threadExitCode); return threadExitCode; } long CMozABConduitSync::PerformSlowSync() { // we take care of first time sync in fast sync in an optimized way return PerformFastSync(); } long CMozABConduitSync::CopyHHtoPC() { long retval=0; BOOL success = FALSE; CONDUIT_LOG0(gFD, "-- SYNC Palm -> Destkop --\n"); if(!m_dbHH) return retval; DWORD mozABCount=0; LONG * mozCatIndexList = NULL; // freed by MSCOM/Mozilla CPString ** mozABNameList = NULL; // freed by MSCOM/Mozilla CPString ** mozABUrlList = NULL; // freed by MSCOM/Mozilla BOOL * mozDirFlagsList = NULL; // freed by MSCOM/Mozilla BOOL neverDidPalmSyncBefore = TRUE; // 1st time palm sync? DWORD mozABIndex; retval = m_dbHH->OpenDB(FALSE); if (!retval) retval = m_dbHH->LoadCategories(); CONDUIT_LOG0(gFD, "Getting moz AB List ... "); if(!retval) retval = m_dbPC->GetPCABList(&mozABCount, &mozCatIndexList, &mozABNameList, &mozABUrlList, &mozDirFlagsList); CONDUIT_LOG1(gFD, "Done getting moz AB List. retval = %d\n", retval); if (retval) return retval; // Create an array to help us identify addrbooks that have been deleted on Palm. DWORD *mozABSeen = (DWORD *) CoTaskMemAlloc(sizeof(DWORD) * mozABCount); if (!mozABSeen) return GEN_ERR_LOW_MEMORY; else memset(mozABSeen, FALSE, sizeof(DWORD) * mozABCount); // See if palm sync was performed before. for(mozABIndex=0; mozABIndexGetBuffer(0), mozABUrlList[mozABIndex]->GetBuffer(0)); } // For each category, try to find the corresponding AB in the moz AB list // and overwrite it with the HH category. CPCategory * pCategory = m_dbHH->GetFirstCategory(); while (pCategory) { CPalmRecord ** recordListHH = NULL; DWORD recordCountHH=0; DWORD catID = pCategory->GetID(); DWORD catIndex = pCategory->GetIndex(); DWORD catFlags = pCategory->GetFlags(); CPString catName(pCategory->GetName()); CONDUIT_LOG3(gFD, "\nProcessing Palm AB '%s' (catIndex/catId) = (%d/%d)... \n", catName.GetBuffer(0), catIndex, catID); BOOL abRenamed = FALSE; BOOL foundInABList=FALSE; for(mozABIndex = 0; mozABIndex < mozABCount; mozABIndex++) { // Palm only allows 15 chars for category names. CPString cutOffName; if (mozABNameList[mozABIndex]->Length() > 15) cutOffName = mozABNameList[mozABIndex]->Left(15); else cutOffName = *mozABNameList[mozABIndex]; // if this category has been synchronized before, check if it has been renamed if(catIndex == mozCatIndexList[mozABIndex]) { CONDUIT_LOG4(gFD, "Category index = %d, name = '%s' moz ab name = %s has been synced before uri = %s\n", catID, catName.GetBuffer(0), mozABNameList[mozABIndex]->GetBuffer(0), mozABUrlList[mozABIndex]->GetBuffer(0)); foundInABList = TRUE; mozABSeen[mozABIndex] = TRUE; // mark it seen // See if the name has been changed on Palm side. Note that if both // Palm category and the corresponding moz addrbook are renamed then // Palm category name takes precedence. if (!CategoryNameMatches(catName, cutOffName, mozDirFlagsList[mozABIndex] & kIsPabDirFlag)) { abRenamed = TRUE; CONDUIT_LOG3(gFD, "Category index = %d, name = '%s' was renamed (from '%s') on Palm so do the same on moz\n", catID, catName.GetBuffer(0), mozABNameList[mozABIndex]->GetBuffer(0)); } break; } // if corresponding category exists if (CategoryNameMatches(catName, cutOffName, mozDirFlagsList[mozABIndex] & kIsPabDirFlag)) { retval = m_dbHH->LoadAllRecordsInCategory(catIndex, &recordListHH, &recordCountHH); CONDUIT_LOG3(gFD, "Category index = %d, name = '%s' matches moz ab %s\n", catID, catName.GetBuffer(0), mozABUrlList[mozABIndex]->GetBuffer(0)); foundInABList = TRUE; mozABSeen[mozABIndex] = TRUE; // mark it seen break; } else CONDUIT_LOG3(gFD, "Category index = %d, name = '%s' doesn't match moz ab %s\n", catID, catName.GetBuffer(0), mozABUrlList[mozABIndex]->GetBuffer(0)); } // end of for // we've got a matching moz AB. So, just delete all the cards in the Moz AB and copy over all the cards // in the HH category. if(!retval && foundInABList) { CPalmRecord ** recordListPC=NULL; DWORD * newRecIDList=NULL; // retval = m_dbPC->DeletePCAB(mozCatIndexList[mozABIndex], *mozABNameList[mozABIndex], *mozABUrlList[mozABIndex]); retval = m_dbHH->LoadAllRecordsInCategory(catIndex, &recordListHH, &recordCountHH); CONDUIT_LOG2(gFD, " Creating new moz AB %s with %d Palm record(s) ... ", mozABNameList[mozABIndex]->GetBuffer(0), recordCountHH); if(!retval) retval = m_dbPC->AddRecords(TRUE, catIndex, *mozABNameList[mozABIndex], recordCountHH, recordListHH); CONDUIT_LOG1(gFD, "Done creating new moz AB. retval=%d.\n", retval); // the MozAB is now synchronized if(!retval) mozDirFlagsList[mozABIndex] &= ~kFirstTimeSyncDirFlag; // delete the PC recordList now that palm is updated if(recordListPC) free(recordListPC); // notify Mozilla that sync is done so that memory can be freed success = retval ? FALSE : TRUE; retval = m_dbPC->NotifySyncDone(success); if(newRecIDList) free(newRecIDList); // See if it was renamed on palm. if (abRenamed) { // We should not rename personal and collected address books here. if (! (mozDirFlagsList[mozABIndex] & kIsPabDirFlag) && mozABUrlList[mozABIndex]->CompareNoCase(COLLECTED_ADDRBOOK_URL)) { CONDUIT_LOG0(gFD, " Renaming AB ... "); retval = m_dbPC->RenamePCAB(catIndex, catName, *mozABUrlList[mozABIndex]); CONDUIT_LOG1(gFD, "Done renaming AB. retval=%d.\n", retval); } } } // If this category can't be found in the moz AB list, then // create a new AB in moz with all records in this category // (even if it's an empty AB). if(!retval && !foundInABList) { CONDUIT_LOG2(gFD, "Category index = %d, name = '%s' is new on palm and needs to be added to moz\n", catID, catName.GetBuffer(0)); retval = m_dbHH->LoadAllRecordsInCategory(catIndex, &recordListHH, &recordCountHH); CONDUIT_LOG2(gFD, " Creating new moz AB %s with %d Palm record(s) ... ", catName.GetBuffer(0), recordCountHH); if(!retval) { CPString mozABName; retval = m_dbPC->AddRecords(FALSE, catIndex, catName, recordCountHH, recordListHH); } CONDUIT_LOG2(gFD, "Done creating new moz AB %s - retval=%d.\n", catName.GetBuffer(0), retval); } // delete and free HH records and recordList once synced if(recordListHH) { CPalmRecord ** tempRecordListHH = recordListHH; for(DWORD i=0; i < recordCountHH; i++) { delete *tempRecordListHH; tempRecordListHH++; } free(recordListHH); } // Process next category pCategory = m_dbHH->GetNextCategory(); } // end of while // Free stuff we allocated. CoTaskMemFree(mozABSeen); // update category info in HH m_dbHH->CompactCategoriesToHH(); // close the HH DB once synced retval = m_dbHH->CloseDB(FALSE); return retval; } long CMozABConduitSync::CopyPCtoHH() { long retval=0; BOOL success = FALSE; CONDUIT_LOG0(gFD, "-- SYNC Destkop-> Palm --\n"); if(!m_dbHH) return retval; DWORD mozABCount=0; LONG * mozCatIndexList = NULL; // freed by MSCOM/Mozilla CPString ** mozABNameList = NULL; // freed by MSCOM/Mozilla CPString ** mozABUrlList = NULL; // freed by MSCOM/Mozilla BOOL * mozDirFlagsList = NULL; // freed by MSCOM/Mozilla BOOL neverDidPalmSyncBefore = TRUE; // 1st time palm sync? DWORD mozABIndex; retval = m_dbHH->OpenDB(FALSE); if (!retval) retval = m_dbHH->LoadCategories(); CONDUIT_LOG0(gFD, "Getting moz AB List ... "); if(!retval) retval = m_dbPC->GetPCABList(&mozABCount, &mozCatIndexList, &mozABNameList, &mozABUrlList, &mozDirFlagsList); if (retval) return retval; CONDUIT_LOG0(gFD, "Done getting moz AB List. \n"); // Create an array to help us identify addrbooks that have been deleted on Palm. DWORD *mozABSeen = (DWORD *) CoTaskMemAlloc(sizeof(DWORD) * mozABCount); if (!mozABSeen) return GEN_ERR_LOW_MEMORY; else memset(mozABSeen, FALSE, sizeof(DWORD) * mozABCount); // See if palm sync was performed before. for(mozABIndex=0; mozABIndexGetBuffer(0), mozABUrlList[mozABIndex]->GetBuffer(0)); } // For each category, try to find the corresponding AB in the moz AB list // and see if it has been synchronized before and take action accordingly. CPCategory * pCategory = m_dbHH->GetFirstCategory(); while (pCategory) { CPalmRecord ** recordListHH = NULL; DWORD recordCountHH=0; DWORD catID = pCategory->GetID(); DWORD catIndex = pCategory->GetIndex(); DWORD catFlags = pCategory->GetFlags(); CPString catName(pCategory->GetName()); CONDUIT_LOG3(gFD, "\nProcessing Palm AB '%s' (catIndex/catId) = (%d/%d)... \n", catName.GetBuffer(0), catIndex, catID); BOOL abRenamed = FALSE; BOOL foundInABList=FALSE; retval = m_dbHH->DeleteCategory(catIndex, FALSE); // delete the category - we'll recreate from moz ab. // Process next category pCategory = m_dbHH->GetNextCategory(); } // end of while // Deal with any Moz AB not existing in Palm, ones not sync'ed above, // and the case where Palm ABs have been deleted. for(mozABIndex=0; mozABIndexGetBuffer(0)); CPalmRecord ** recordListPC=NULL; DWORD recordCountPC=0; DWORD * newRecIDList=NULL; CPCategory cat; retval = m_dbPC->LoadAllRecords(*mozABNameList[mozABIndex], &recordCountPC, &recordListPC); if(!retval) { if ((mozDirFlagsList[mozABIndex] & kIsPabDirFlag)) cat.SetName("Personal"); else cat.SetName(mozABNameList[mozABIndex]->GetBuffer(0)); CONDUIT_LOG1(gFD, " Creating new Palm AB with %d record(s) ... ", recordCountPC); retval = m_dbHH->AddCategory(cat); CONDUIT_LOG2(gFD, "Done creating new Palm AB, new category index=%d. retval=%d.\n", cat.GetIndex(), retval); if(!retval) { CONDUIT_LOG1(gFD, " Adding %d record(s) to new Palm AB ... ", recordCountPC); newRecIDList = (DWORD *) calloc(recordCountPC, sizeof(DWORD)); for (unsigned long i=0; i < recordCountPC; i++) { if(!recordListPC[i]) continue; CPalmRecord palmRec = *recordListPC[i]; palmRec.SetCategory(cat.GetIndex()); retval = m_dbHH->AddARecord(palmRec); // should we check existing recs? newRecIDList[i] = palmRec.GetID(); delete recordListPC[i]; // delete the record now that it is used } CONDUIT_LOG0(gFD, "Done adding new records to new Palm AB.\n"); } else CONDUIT_LOG1(gFD, "Creating new Palm AB failed. retval=%d.\n", retval); } else CONDUIT_LOG1(gFD, " Loading moz AB records failed so can't create new Palm AB. retval=%d.\n", retval); // delete the recordList now that palm is updated if(recordListPC) free(recordListPC); // notify Mozilla that sync is done so that memory can be freed if(!retval) success = TRUE; else { success = FALSE; recordCountPC=0; } retval = m_dbPC->NotifySyncDone(success, cat.GetIndex(), recordCountPC, newRecIDList); if(newRecIDList) free(newRecIDList); // Lastly, update the AB with new category index and mod time. retval = m_dbPC->UpdatePCABSyncInfo(success ? cat.GetIndex() : -1, *mozABNameList[mozABIndex]); } // end of mozAB not existing in Palm for loop // Purge deleted Palm record permanently (in case they were logically deleted). m_dbHH->PurgeDeletedRecs(); // Free stuff we allocated. CoTaskMemFree(mozABSeen); // update category info in HH m_dbHH->CompactCategoriesToHH(); // close the HH DB once synced retval = m_dbHH->CloseDB(FALSE); return retval; }