RetroZilla/mailnews/extensions/palmsync/conduit/MozABConduitSync.cpp
2015-10-20 23:03:22 -04:00

1021 lines
41 KiB
C++

/* ***** 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 <rdayal@netscape.com>
*
* 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 <windows.h>
#include "syncmgr.h"
#include <tchar.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#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( &ltime );
CONDUIT_LOG1(gFD, "\n------------ START OF PALM SYNC ------------ at %s", ctime(&ltime));
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( &ltime );
CONDUIT_LOG1(gFD, "------------ END OF PALM SYNC -------------- at %s\n", ctime(&ltime));
// 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; mozABIndex<mozABCount; mozABIndex++)
if (! (mozDirFlagsList[mozABIndex] & kFirstTimeSyncDirFlag))
{
neverDidPalmSyncBefore = FALSE;
break;
}
// Log moz addrbooks.
for (mozABIndex=0; mozABIndex<mozABCount; mozABIndex++)
{
CONDUIT_LOG5(gFD, "Moz AB[%d] category index/synced=%d/%d, name= '%s', url= '%s'\n",
mozABIndex, mozCatIndexList[mozABIndex], ! (mozDirFlagsList[mozABIndex] & kFirstTimeSyncDirFlag),
mozABNameList[mozABIndex]->GetBuffer(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; 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
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; mozABIndex<mozABCount; mozABIndex++)
{
if((mozDirFlagsList[mozABIndex] & kFirstTimeSyncDirFlag || neverDidPalmSyncBefore || initialHHSync) && !sync->CategoryExists(*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; mozABIndex<mozABCount; mozABIndex++)
if (! (mozDirFlagsList[mozABIndex] & kFirstTimeSyncDirFlag))
{
neverDidPalmSyncBefore = FALSE;
break;
}
// Log moz addrbooks.
for (mozABIndex=0; mozABIndex<mozABCount; mozABIndex++)
{
CONDUIT_LOG5(gFD, "Moz AB[%d] category index/synced=%d/%d, name= '%s', url= '%s'\n",
mozABIndex, mozCatIndexList[mozABIndex], !(mozDirFlagsList[mozABIndex] & kFirstTimeSyncDirFlag),
mozABNameList[mozABIndex]->GetBuffer(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; mozABIndex<mozABCount; mozABIndex++)
if (! (mozDirFlagsList[mozABIndex] & kFirstTimeSyncDirFlag))
{
neverDidPalmSyncBefore = FALSE;
break;
}
// Log moz addrbooks.
for (mozABIndex=0; mozABIndex<mozABCount; mozABIndex++)
{
CONDUIT_LOG5(gFD, "Moz AB[%d] category index/synced=%d/%d, name= '%s', url= '%s'\n",
mozABIndex, mozCatIndexList[mozABIndex], !(mozDirFlagsList[mozABIndex] & kFirstTimeSyncDirFlag),
mozABNameList[mozABIndex]->GetBuffer(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; mozABIndex<mozABCount; mozABIndex++)
{
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 = 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;
}