Logo Search packages:      
Sourcecode: jpilot-syncmal version File versions  Download package

libmal.c

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* The contents of this file are subject to the Mozilla Public License
 * Version 1.0 (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 Mobile Application Link.
 *
 * The Initial Developer of the Original Code is AvantGo, Inc.
 * Portions created by AvantGo, Inc. are Copyright (C) 1997-1999
 * AvantGo, Inc. All Rights Reserved.
 *
 */
/*

  See the README file in this directory for info on compiling, using
  and the state of this program. If the readme file is for some reason
  not there, it can be found at the MAL website:

  http://corp.avantgo.com/mal/

*/
/* Thu, 29 Jul 1999 12:43:01 +0200
 *     Turbo Fredriksson <turbo@nocrew.org>
 *     Added daemon mode (close STDIO and disconnect from the shell
 *     Rewrote the command line parsing (to use getopt_long)
 */
/*
 * 25 Jan 2000
 * Jason Day <jasonday@worldnet.att.net>
 * Added code for submission of .sub files
 */
/*
 * 15 Mar 2000
 * Jason Day <jasonday@worldnet.att.net>
 * Put most of the code into a library
 */

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#ifndef _HPUX_SOURCE
#include <dlfcn.h>
#endif
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>

#include <AGNet.h>
#include <AGUtil.h>
#include <AGClientProcessor.h>
#include <AGProtocol.h>
#include <AGBufferReader.h>
#include <AGPalmProtocol.h>
#include <AGUserConfig.h>
#include <AGServerConfig.h>
#include <AGSyncCommon.h>
#include <AGCommandProcessor.h>
#include <AGDesktopInfoPalm.h>
#include <AGTimeoutMessageBox.h>
#include <AGMobileLinkSettings.h>
#include <MAL31UserConfig.h>

#include <pi-source.h>
#include <pi-socket.h>
#include <pi-file.h>
#include <pi-dlp.h>
#include <pi-version.h>
#include <pi-header.h>

#include "libplugin.h"
#include "libmal.h"

#define DEFAULT_CARD_NUM 0

#define VERSION_STRING "malsync version 2.1.1"

static char *device = "/dev/pilot";
static char *httpProxy      = NULL;
static int   httpProxyPort  = 0;
static char *socksProxy     = NULL;
static int   socksProxyPort = 0;
static char *proxyUsername  = NULL;
static char *proxyPassword  = NULL;
static char *subfile        = NULL;

#ifdef _DEBUG
#define debug_print(x) printf("%s\n", (x));
#else
#define debug_print(x)
#endif

/* ----------------------------------------------------------------------------*/

/*
 * Setter methods for the proxy and socks variables.
 */

void setHttpProxy (char *str) {
    httpProxy = str;
}

void setHttpProxyPort (int port) {
    httpProxyPort = port;
}

void setSocksProxy (char *str) {
    socksProxy = str;
}

void setSocksProxyPort (int port) {
    socksProxyPort = port;
}

void setProxyUsername (char *str) {
    proxyUsername = str;
}

void setProxyPassword (char *str) {
    proxyPassword = str;
}

int null_status(const char *null, ...)
{
      return 0;
}


static int sd = 0;
static int verbose = 0;
static int threeone = 0;
static int lowres = 0;

/* ----------------------------------------------------------------------------*/
static long openUserConfigDatabase(int *threeone);
static int32 readDeviceUserConfig32(int userConfigDBHandle, AGUserConfig **deviceUserConfig);
static int32 readDeviceUserConfig31(int userConfigDBHandle, AGUserConfig **deviceUserConfig);
static int32 readDeviceUserConfig(int userConfigDBHandle,
                                  AGUserConfig **deviceUserConfig,
                                  int threeone);
static void writeDeviceUserConfig(int userConfigDBHandle,
                                  AGUserConfig * deviceUserConfig,
                                  recordid_t *recID, int threeone);

static int32 initAndOpenDatabase(void *out, AGDBConfig *theDatabase,
                                 int32 *errCode);
static int32 getNextModifiedRecord(void * out, AGRecord ** record,
                                   int32 *errCode);
static int32 getNextRecord(void * out, AGRecord ** record,
                           int32 *errCode);

static int32 cmdTASK(void *out, int32 *returnErrorCode, char *currentTask,
                     AGBool bufferable);
static int32 cmdITEM(void *out, int32 *returnErrorCode,
                                   int32 currentItemNumber,
                                   int32 totalItemCount,
                                   char *currentItem);
static int32 cmdDELETEDATABASE(void *out, int32 *returnErrorCode,
                                             char *dbname);
static int32 cmdOPENDATABASE(void *out, int32 *returnErrorCode,
                                           char *dbname);
static int32 cmdCLOSEDATABASE(void *out, int32 *returnErrorCode);
static int32 cmdCLEARMODS(void *out, int32 *returnErrorCode);
static int32 cmdGOODBYE(void *out, int32 *returnErrorCode,
                        AGSyncStatus syncStatus,
                        int32 errorCode,
                        char *errorMessage);
static int32 cmdRECORD(void *out, int32 *returnErrorCode,
                       int32 *newUID,
                       int32 uid,
                       AGRecordStatus mod,
                       int32 recordDataLength,
                       void *recordData,
                       int32 platformDataLength,
                       void *platformData);
static netInitFunc     secnetinit = NULL;
static netCloseFunc    secnetclose = NULL;
static netCtxSizeFunc  secctxsize = NULL;
static netPreSyncHook  secnetpresync = NULL;
static netPostSyncHook  secnetpostsync = NULL;

/*----------------------------------------------------------------------------*/
int loadSecLib(AGNetCtx **ctx)
{
    char *seclib;

    seclib = getenv("MALSYNC_SECURITYLIB");

    if (!seclib) {
        return 0;
    }

#ifdef _WIN32
    {
        HINSTANCE h = LoadLibrary(seclib);
        if (h) {
            secnetinit = (netInitFunc)GetProcAddress(h, "NetInit");
            secnetclose = (netCloseFunc)GetProcAddress(h, "NetClose");
            secctxsize = (netCtxSizeFunc)GetProcAddress(h, "NetGetCtxSize");
            secnetpostsync =
                (netPostSyncHook)GetProcAddress(h, "NetPostSyncHook");
            secnetpresync = (netPreSyncHook)GetProcAddress(h, "NetPreSyncHook");
        }
    }
#else /* _WIN32 */
    {
#ifndef _HPUX_SOURCE
        void *h;
#ifdef __linux__
        h  = dlopen(seclib, RTLD_GLOBAL|RTLD_NOW);
#else /* __linux__ */
        h  = dlopen(seclib, RTLD_NOW);
#endif /* __linux */

        if (h) {
            secnetinit = dlsym(h, "NetInit");
            secnetclose = dlsym(h, "NetClose");
            secctxsize = dlsym(h, "NetGetCtxSize");
            secnetpostsync = dlsym(h, "NetPostSyncHook");
            secnetpresync = dlsym(h, "NetPreSyncHook");
        } else {
            if (verbose)
                printf("%s\n", dlerror());
        }
#endif
    }
#endif /* !_WIN32 */

    if (secnetinit && secnetclose && secctxsize ) {
        *ctx = calloc(1, (*secctxsize)());
        (*secnetinit)(*ctx);
        return 1;
    }

    return 0;
}

/* ----------------------------------------------------------------------------*/
void syncInfoFree(PalmSyncInfo * pInfo)
{

    if (NULL != pInfo) {

        if (NULL != pInfo->platform)
            free(pInfo->platform);

        if (NULL != pInfo->userConfig)
            AGUserConfigFree(pInfo->userConfig);

        if (NULL != pInfo->pilot_buffer)
            free(pInfo->pilot_buffer);

        if (NULL != pInfo->commandProcessor)
            AGCommandProcessorFree(pInfo->commandProcessor);

        free(pInfo);
    }
}

/* ----------------------------------------------------------------------------*/
PalmSyncInfo * syncInfoNew()
{
    PalmSyncInfo * pInfo;

    /* Allocate the PalmSyncInfo structure. */
    pInfo = (PalmSyncInfo *)malloc(sizeof(PalmSyncInfo));
    if (NULL != pInfo) {

        const int pbs = 65535;

        bzero(pInfo, sizeof(PalmSyncInfo));

        pInfo->pilot_buffer_size    = pbs;
        pInfo->pilot_buffer         = (uint8 *)malloc(pbs);
        if (NULL == pInfo->pilot_buffer)
            goto fail;

        /* Allocate the platform calls record. */
        pInfo->platform = (AGPlatformCalls *)malloc(sizeof(AGPlatformCalls));
        bzero(pInfo->platform, sizeof(AGPlatformCalls));
        if (NULL == pInfo->platform)
            goto fail;

        return pInfo;
    }

    fail:
    if (NULL != pInfo)
        syncInfoFree(pInfo);

    return NULL;
}

/* ----------------------------------------------------------------------------*/
static AGBool setupPlatformCalls(PalmSyncInfo * pInfo)
{
    pInfo->platform->out = pInfo;
    pInfo->platform->nextModifiedRecordFunc = getNextModifiedRecord;
    pInfo->platform->nextRecordFunc = getNextRecord;
    pInfo->platform->openDatabaseFunc =  initAndOpenDatabase;
    return FALSE;
}
/*---------------------------------------------------------------------------*/
static int32
readInt32(uint8 *p)
{
    return (((int32)p[0]) << 24)
        + (((int32)p[1]) << 16)
        + (((int32)p[2]) << 8)
        + ((int32)p[3]);
}
/*---------------------------------------------------------------------------*/
static
int16 readInt16(uint8 * p)
{
    return (((int16)p[0]) << 8) + ((int16)p[1]);
}

/*---------------------------------------------------------------------------*/
static void
readAndUseDeviceInfoDatabase(AGDeviceInfo * devInfo,
                             uint8 *dev_db_info_buffer,
                             uint32 dev_db_info_buffer_size)
{
    int database_id = 0;
    long result;

    if (verbose)
        printf("Entering readAndUseDeviceInfoDatabase\n");

    /*  Open the device info database on the device.  It may or may not
     be present.  If it isn't, that's ok -- just return and don't
     change anything.
     */
    /* 11/24/00 - Changed name of the database that the color info is stored
     * in. This should clear up some bug reports from people with color
     * devices.
     */
    result = dlp_OpenDB(sd, DEFAULT_CARD_NUM, dlpOpenRead,
                        "AvGoDeviceInfo", &database_id);

    if (result < 0) {
        if (verbose)
            printf("Unable to open MBlnDevice Info\n");

    } else {

        int attr = 0;
        int cat  = 0;
        recordid_t id;
        int rc;

        rc = dlp_ReadRecordByIndex(sd, database_id, 0,
                                   (void *)dev_db_info_buffer,
                                   &id, &dev_db_info_buffer_size,
                                   &attr, &cat);


        if (rc >= 0) {
            uint8 *p = dev_db_info_buffer;
            int16 dev_db_info_version = readInt16(p);
            p+=sizeof(int16);
            devInfo->colorDepth = readInt32(p);
            p+=sizeof(int32);
            devInfo->screenWidth = readInt32(p);
            p+=sizeof(int32);
            devInfo->screenHeight = readInt32(p);
            p+=sizeof(int32);

            if (devInfo->serialNumber)
                free(devInfo->serialNumber);

            /*  Next line is safe because we know p isn't null
             at this point and we know the creator of the
             record wrote at least a zero here.
             */
            devInfo->serialNumber = strdup((char*)p);

            if (verbose)
                printf("MBlnDeviceInfo sez: colorDepth = %d,"
                       " serial number is %s\n",
                       devInfo->colorDepth, devInfo->serialNumber);

        }

        dlp_CloseDB(sd, database_id);
    }
}


/* ----------------------------------------------------------------------------*/
static int readDeviceInfo(PalmSyncInfo * pInfo)
{
    AGDeviceInfo * devInfo;
    struct SysInfo sysInfo;
    struct CardInfo cardInfo;
    char osverstring[24];
    int err;
    int majorVersion, minorVersion, bugfixVersion, build, state;

    /* Start with clean slate. */
    devInfo = pInfo->deviceInfo;

    err = dlp_ReadSysInfo(sd, &sysInfo);
    if (err < 0) {
      jp_logf(JP_LOG_FATAL,"dlp_ReadSysInfo failed with err %d\n", err);
        return -1;
    }

    cardInfo.card = DEFAULT_CARD_NUM;
    err = dlp_ReadStorageInfo(sd, DEFAULT_CARD_NUM, &cardInfo);
    if (err < 0) {
        jp_logf(JP_LOG_FATAL,"dlp_ReadStorageInfo failed with err %d\n", err);
        return -1;
    }

    majorVersion = (((sysInfo.romVersion >> 28) & 0xf) * 10) +
        ((sysInfo.romVersion >> 24) & 0xf);
    minorVersion = ((sysInfo.romVersion >> 20) & 0xf);
    bugfixVersion = ((sysInfo.romVersion >> 16) & 0xf);
    state = ((sysInfo.romVersion >> 12) & 0xf);
    build = (((sysInfo.romVersion >> 8) & 0xf) * 10) +
        (((sysInfo.romVersion >> 4) & 0xf) * 10)+ (sysInfo.romVersion  & 0xf);

    g_snprintf(osverstring, 24, "%d.%d", majorVersion, minorVersion);

    devInfo->availableBytes   = cardInfo.ramFree;
    devInfo->serialNumber     = strdup("");
    devInfo->osName           = strdup("PALM_OS");
    devInfo->osVersion        = strdup(osverstring);
    devInfo->screenWidth      = 150;
    devInfo->screenHeight     = 150;

    if((majorVersion > 3) || (majorVersion == 3 && minorVersion >= 5))
        devInfo->colorDepth = 8;
    else {
        if(majorVersion > 2)
            devInfo->colorDepth = 2;
        else
            devInfo->colorDepth = 1;
    }

    if (verbose) {
        printf("Setting colordepth: devInfo->colorDepth = %d\n",
               devInfo->colorDepth);
    }

    readAndUseDeviceInfoDatabase(devInfo,
                                 pInfo->pilot_buffer,
                                 pInfo->pilot_buffer_size);

    /* Override the color depth if the user wants low res images. */
    if (lowres) {
        if (verbose) {
            printf("Overriding colordepth: devInfo->colorDepth = 1\n");
        }
        devInfo->colorDepth = 1;
    }


    return 0;
}
/* ----------------------------------------------------------------------------*/
static AGBool getPalmDatabaseCreationInfo(AGDBConfig * db, uint32 * creator,
                                          uint32 * flags, uint32 * type)
{
    AGBufferReader * r = NULL;
    debug_print("GetPalmDatabaseCreationInfo()\n");

    if (NULL == db)
        return FALSE;

    if (0 == db->platformDataLength || NULL == db->platformData)
        return FALSE;

    r = AGBufferReaderNew((uint8*)db->platformData);
    if (NULL == r)
        return FALSE;

    AGPalmReadDBConfigPlatformData((AGReader*)r, creator, type, flags);
    AGBufferReaderFree(r);
    return TRUE;
}

/* ----------------------------------------------------------------------------*/
static int createDatabase(AGDBConfig *db)
{
    int dbhandle;
    long creator;
    int flags;
    int cardNo = DEFAULT_CARD_NUM;
    long type;
    int version = 0;
    int err;

    if (!db)
        return 0;

#ifdef _DEBUG
    printf("createDatabase\n");
#endif

    getPalmDatabaseCreationInfo(db, (uint32*)&creator,
                                (uint32*)&flags, (uint32*)&type);

    if ((err = dlp_CreateDB(sd,  creator,  type, cardNo, flags,
                            version, db->dbname, &dbhandle)) < 0) {
#ifdef _DEBUG
        printf("createDatabase: dlp_CreateDB failed err = %d\n", err);
#endif

        dbhandle = 0;
    }

    return dbhandle;
}

/* ----------------------------------------------------------------------------*/
static long openDatabase(PalmSyncInfo *pInfo, char *dbname, AGBool create)
{

    long result;

    if (!dbname || !pInfo) {
        debug_print("\n");
        return -1;
    }
    debug_print("... opening '");
    debug_print(dbname);
    debug_print("' ... ");

    pInfo->currentDb =
        AGServerConfigGetDBConfigNamed(pInfo->currentServerConfig, dbname);

    result = dlp_OpenDB(sd, DEFAULT_CARD_NUM, dlpOpenRead|dlpOpenWrite,
                        dbname, &pInfo->pilot_rHandle);

    if ((result < 0) && create)
        pInfo->pilot_rHandle = createDatabase(pInfo->currentDb);

    if (pInfo->pilot_rHandle) {
        uint32 creator, flags, type;
        if (getPalmDatabaseCreationInfo(pInfo->currentDb, &creator, &flags,
                                        &type) && (flags & 0x01) != 0) {
            pInfo->currentDBIsResourceType = TRUE;
        } else
            pInfo->currentDBIsResourceType = FALSE;
        debug_print("successfully.\n");
    } else {
        debug_print("unsuccessfully.\n");
        pInfo->currentDBIsResourceType = FALSE;
        pInfo->currentDb = NULL;
    }

    return result;
}

/* ----------------------------------------------------------------------------*/
static long closeDatabase(PalmSyncInfo * pInfo)
{
    int result;

    result = dlp_CloseDB(sd, pInfo->pilot_rHandle);
    pInfo->pilot_rHandle = 0;
    pInfo->currentDb = NULL;
    pInfo->currentDBIsResourceType = FALSE;
    return result;
}

/* ----------------------------------------------------------------------------*/
static void deleteDatabase(char * dbname)
{
    debug_print("deleteDatabase()\n");
    dlp_DeleteDB(sd, DEFAULT_CARD_NUM, dbname);
}
/* ----------------------------------------------------------------------------*/
static void clearMods(long dbHandle)
{
    debug_print("clearMods()\n");
    dlp_CleanUpDatabase(sd, dbHandle);
    dlp_ResetSyncFlags(sd, dbHandle);

}
#define DEVICE_USERCONFIG_DB_NAME "MBlnUserConfig"
/* ----------------------------------------------------------------------------*/
static long openUserConfigDatabase(int *threeone)
{
    long result;
    int userConfigDBHandle = 0;

    *threeone = 0;
    result = dlp_OpenDB(sd, DEFAULT_CARD_NUM, dlpOpenRead|dlpOpenWrite,
                        DEVICE_PROFILE_DB_NAME,
                        &userConfigDBHandle);

    if (result < 0) {

        /* OK Now lets look for a 3.1 client database */

        result = dlp_OpenDB(sd, DEFAULT_CARD_NUM, dlpOpenRead|dlpOpenWrite,
                            DEVICE_USERCONFIG_DB_NAME,
                            &userConfigDBHandle);
        if (result < 0) {
            result = dlp_CreateDB(sd, DEVICE_PROFILE_DB_CREATOR,
                                  DEVICE_PROFILE_DB_TYPE, DEFAULT_CARD_NUM,
                                  0, 0, DEVICE_PROFILE_DB_NAME,
                                  &userConfigDBHandle);
            if (result < 0) {
                fprintf(stderr, "Unable to create user Config Databage\n");
                userConfigDBHandle = 0;
            }
        } else {
            *threeone = 1;
        }

    }
    return userConfigDBHandle;
}

#define BUFFERSIZE 0xFFFF
/* ----------------------------------------------------------------------------*/
static int32
readDeviceUserConfig32(int userConfigDBHandle, AGUserConfig **deviceUserConfig)
{
    recordid_t id;
    int bufferSize = BUFFERSIZE;
    int attr = 0;
    int cat  = 0;
    int rc;
    uint8 buffer[BUFFERSIZE];
    AGBufferReader * r = NULL;

    rc = dlp_ReadRecordByIndex(sd, userConfigDBHandle, 0, (void *)buffer,
                               &id, &bufferSize, &attr, &cat);

    if (rc < 0) {
#ifdef _DEBUG
        printf("readDeviceUserConfig: dlp_ReadRecordByIndex , err = %d\n",
               rc);
#endif
        return 0;
    }

    r = AGBufferReaderNew(buffer);
    if (r) {
        *deviceUserConfig = AGUserConfigNew();
        AGUserConfigReadData(*deviceUserConfig, (AGReader*)r);
        AGBufferReaderFree(r);
        return id;
    } else
        return 0;
}
#define BUFFERSIZE 0xFFFF
/*---------------------------------------------------------------------------*/
static int32 readDeviceUserConfig31(int userConfigDBHandle,
                                    AGUserConfig **deviceUserConfig)
{
    recordid_t id;
    int bufferSize = BUFFERSIZE;
    int attr = 0;
    int cat  = 0;
    int rc;
    uint8 buffer[BUFFERSIZE];
    AGBufferReader * r = NULL;

    rc = dlp_ReadRecordByIndex(sd, userConfigDBHandle, 0, (void *)buffer,
                               &id, &bufferSize, &attr, &cat);

    if (rc < 0) {
#ifdef _DEBUG
        printf("readDeviceUserConfig: dlp_ReadRecordByIndex , err = %d\n",
               rc);
#endif
        return 0;
    }

    r = AGBufferReaderNew(buffer);
    if (r) {
        *deviceUserConfig = AGUserConfigNew();
        MAL31ReadUserData(*deviceUserConfig, (AGReader*)r);
        AGBufferReaderFree(r);
        return id;
    } else
        return 0;
}
/*---------------------------------------------------------------------------*/
static int32 readDeviceUserConfig(int userConfigDBHandle,
                                  AGUserConfig **deviceUserConfig,
                                  int threeone)
{
    int32 ret;
    if (threeone)
        ret = readDeviceUserConfig31(userConfigDBHandle, deviceUserConfig);
    else
        ret = readDeviceUserConfig32(userConfigDBHandle, deviceUserConfig);
    return ret;
}

/* ----------------------------------------------------------------------------*/
static void writeDeviceUserConfig(int userConfigDBHandle,
                                  AGUserConfig * deviceUserConfig,
                                  recordid_t *recID, int threeone)
{

    recordid_t id;
    int bufferSize = BUFFERSIZE;
    int attr = 0;
    int cat  = 0;
    uint8 buffer[BUFFERSIZE];
    AGBufferWriter * w = NULL;
    w = AGBufferWriterNew(0);
    if (w) {
        long result;

        if (threeone) {
            MAL31WriteUserData(deviceUserConfig, (AGWriter*)w);
        } else {
            AGUserConfigWriteData(deviceUserConfig, (AGWriter*)w);
        }

        result = dlp_ReadRecordByIndex(sd, userConfigDBHandle, 0, (void *)buffer,
                                       &id, &bufferSize, &attr, &cat);

        if (result < 0)
            id = 0;

        result =  dlp_WriteRecord(sd, userConfigDBHandle, 0,
                                  id, 0, (void *)AGBufferWriterGetBuffer(w),
                                  AGBufferWriterGetBufferSize(w),
                                  &id);
        AGBufferWriterFree(w);

    }
}

/* ----------------------------------------------------------------------------*/
static AGUserConfig *getUserConfig(uint32 * pilotID)
{

    /* The device is the truth. There is no way to set these values on
       the desktop */
    AGUserConfig * deviceUserConfig = NULL;
    int userConfigDBHandle = 0;

    /* Get device's record. */
    userConfigDBHandle = openUserConfigDatabase(&threeone);
    if (userConfigDBHandle) {

        /* Retrieve device's idea of current userConfig. */
        *pilotID = readDeviceUserConfig(userConfigDBHandle,
                                        &deviceUserConfig,
                                        threeone);

        /* Done with database for now, so close it. */
        dlp_CloseDB(sd, userConfigDBHandle);


    }
    return deviceUserConfig;
}

/* ----------------------------------------------------------------------------*/
static void storeDeviceUserConfig(AGUserConfig *userConfig, recordid_t id)
{
    int threeone;
    int userConfigDBHandle = openUserConfigDatabase(&threeone);
    if (0 != userConfigDBHandle) {
        writeDeviceUserConfig(userConfigDBHandle,
                              userConfig, &id, threeone);
        dlp_CloseDB(sd, userConfigDBHandle);
    }
}

/* ----------------------------------------------------------------------------*/
static void doStartServer(PalmSyncInfo * pInfo,
                          AGServerConfig *sc,
                          int32 *errCode)
{
    pInfo->currentServerConfig = sc;
    if(pInfo->commandProcessor) {
        AGCommandProcessorFree(pInfo->commandProcessor);
        pInfo->commandProcessor = NULL;
    }
    pInfo->commandProcessor = AGCommandProcessorNew(sc);
    pInfo->platform->performCommandOut = pInfo->commandProcessor;
    pInfo->platform->performCommandFunc =
                    AGCommandProcessorGetPerformFunc(pInfo->commandProcessor);

    pInfo->commandProcessor->commands.out = pInfo;

    pInfo->commandProcessor->commands.performTaskFunc = cmdTASK;
    pInfo->commandProcessor->commands.performItemFunc = cmdITEM;
    pInfo->commandProcessor->commands.performDeleteDatabaseFunc = cmdDELETEDATABASE;
    pInfo->commandProcessor->commands.performOpenDatabaseFunc = cmdOPENDATABASE;
    pInfo->commandProcessor->commands.performCloseDatabaseFunc = cmdCLOSEDATABASE;
    pInfo->commandProcessor->commands.performClearModsFunc = cmdCLEARMODS;
    pInfo->commandProcessor->commands.performGoodbyeFunc = cmdGOODBYE;
    pInfo->commandProcessor->commands.performRecordFunc = cmdRECORD;

}

/* ----------------------------------------------------------------------------*/
static void doEndServer(PalmSyncInfo * pInfo,
                        int32 *errCode)
{
    pInfo->currentServerConfig = NULL;
    if(pInfo->commandProcessor) {
        AGCommandProcessorFree(pInfo->commandProcessor);
        pInfo->commandProcessor = NULL;
    }
}
/* ----------------------------------------------------------------------------*/
static int32 cmdTASK(void *out, int32 *returnErrorCode, char *currentTask,
                     AGBool bufferable)
{
    if (currentTask) {
      jp_logf(JP_LOG_GUI,"%s\n", currentTask);
    }
    return AGCLIENT_CONTINUE;
}
/* ----------------------------------------------------------------------------*/
static int32 cmdITEM(void *out, int32 *returnErrorCode,
                                   int32 currentItemNumber,
                                   int32 totalItemCount,
                                   char *currentItem)
{
    jp_logf(JP_LOG_GUI,".");
    if (currentItemNumber == totalItemCount) {
      jp_logf(JP_LOG_GUI,"\n");
    }

    return AGCLIENT_CONTINUE;
}
/* ----------------------------------------------------------------------------*/
static int32 cmdDELETEDATABASE(void *out, int32 *returnErrorCode,
                                             char *dbname)
{
    debug_print("doCmdAG_DELETEDATABASE_CMD()\n");

    if (NULL != dbname) {
        debug_print("... trying to delete database ");
        debug_print(dbname);
        debug_print(" from device.\n");
        deleteDatabase(dbname);
    }
    return AGCLIENT_CONTINUE;
}
/*----------------------------------------------------------------------------*/
static int32 cmdOPENDATABASE(void *out, int32 *returnErrorCode, char *dbname)
{
    PalmSyncInfo *pInfo = (PalmSyncInfo *)out;
    debug_print("doCmdAG_OPENDATABASE_CMD()\n");

    if (NULL != dbname) {
        long result;
        /* We assign a result code here only for debugging.  It's ok for an
        open to fail here. */
        result = openDatabase(pInfo, dbname, TRUE);
    }
    return AGCLIENT_CONTINUE;
}
/*----------------------------------------------------------------------------*/
static int32 cmdCLOSEDATABASE(void *out, int32 *returnErrorCode)
{
    PalmSyncInfo *pInfo = (PalmSyncInfo *)out;
    debug_print("doCmdAG_CLOSEDATABASE_CMD()\n");
    closeDatabase(pInfo);
    return AGCLIENT_CONTINUE;
}
/*----------------------------------------------------------------------------*/
static int32 cmdCLEARMODS(void *out, int32 *returnErrorCode)
{
    PalmSyncInfo *pInfo = (PalmSyncInfo *)out;
    debug_print("doCmdAG_CLEARMODS_CMD()\n");
    clearMods(pInfo->pilot_rHandle);
    return AGCLIENT_CONTINUE;
}
/*----------------------------------------------------------------------------*/
static int32 cmdGOODBYE(void *out, int32 *returnErrorCode,
                        AGSyncStatus syncStatus,
                        int32 errorCode,
                        char *errorMessage)
{
    debug_print("doCmdAG_GOODBYE_CMD()\n");

    if (errorMessage) {
      jp_logf(JP_LOG_FATAL,"%s\n", errorMessage);
    }

    return AGCLIENT_CONTINUE;
}
/*----------------------------------------------------------------------------*/
int getIndexFromPlatformData(uint8 *platformData)
{
    int16 recIndex;
    AGBufferReader reader;

    if (!platformData)
        return 0;

    AGBufferReaderInit(&reader, platformData);
    AGPalmReadRecordPlatformData((AGReader *)&reader, &recIndex);
    AGBufferReaderFinalize(&reader);
    return (int)recIndex;
}
/*----------------------------------------------------------------------------*/
static int32 cmdRECORD(void *out, int32 *returnErrorCode,
                       int32 *newUID,
                       int32 uid,
                       AGRecordStatus mod,
                       int32 recordDataLength,
                       void *recordData,
                       int32 platformDataLength,
                       void *platformData)
{
    PalmSyncInfo *pInfo = (PalmSyncInfo *)out;

    debug_print("doCmdAG_RECORD_CMD()\n");

    if(mod == AG_RECORD_NEW_TEMPORARY_UID) {
        uid = 0;
    }

    if (AG_RECORD_DELETED == mod) {

        dlp_DeleteRecord(sd, pInfo->pilot_rHandle, 0, uid);

    } else if (recordDataLength <= 0x0000ffff) {

        if (pInfo->currentDBIsResourceType) {

            dlp_WriteRecord(sd, pInfo->pilot_rHandle, dlpDBFlagResource,
                            uid, 0, (void *)recordData,
                            recordDataLength, (recordid_t *)newUID);
            debug_print("doCmdAG_RECORD_CMD()\n");


        } else {

            dlp_WriteRecord(sd, pInfo->pilot_rHandle, 0,
                            uid, 0, (void *)recordData,
                            recordDataLength, (recordid_t *)newUID);
        }

    }
    return AGCLIENT_CONTINUE;
}
/*----------------------------------------------------------------------------*/
static int32 initAndOpenDatabase(void *_pInfo, AGDBConfig *db,
                                    int32 *errCode)
{
    long result;
    PalmSyncInfo * pInfo = (PalmSyncInfo *)_pInfo;

    if (NULL == db->dbname) {
        *errCode = AGCLIENT_OPEN_ERR;
        return AGCLIENT_ERR;
    }

    result = openDatabase(pInfo, db->dbname, FALSE);
    if (result < 0) {
        if (result == dlpErrNotFound)
            *errCode = AGCLIENT_OPEN_ERR;
        else
            *errCode = AGCLIENT_UNKNOWN_ERR;
        return AGCLIENT_ERR;
    }

    pInfo->pilot_RecIndex = 0;
    pInfo->record = AGRecordNew(0, AG_RECORD_UNMODIFIED, 0, 0, 0, 0);
    if (!pInfo->record) {
        *errCode = AGCLIENT_OPEN_ERR;
        return AGCLIENT_ERR;
    }

    return AGCLIENT_IDLE;
}
/*----------------------------------------------------------------------------*/
static int32 leaveGetRecord(PalmSyncInfo * pInfo, int32 result)
{
    if (pInfo->record) {

        /* Set recordData to NULL so that AGRecordFree doesn't try
        to free it (we own that buffer and will release it when the
        program ends). */
        pInfo->record->recordData = NULL;

        AGRecordFree(pInfo->record);
        pInfo->record = NULL;
    }
    return result;
}
/*----------------------------------------------------------------------------*/
static int32 getRecordBase(PalmSyncInfo * pInfo, AGBool modonly,
                           AGRecord ** record, int32 * errCode)
{
    int32 result;
    int att = 0;
    int cat = 0;
    int size = pInfo->pilot_buffer_size;
    int idx   = pInfo->pilot_RecIndex++;

    result = (modonly) ?
        dlp_ReadNextModifiedRec (sd, pInfo->pilot_rHandle, pInfo->pilot_buffer,
                                 &pInfo->id, &idx,
                                 &size, &att, &cat)
        :
        dlp_ReadRecordByIndex(sd, pInfo->pilot_rHandle, idx,
                              pInfo->pilot_buffer, &pInfo->id,
                              &size, &att, &cat);

    if (result < 0) {
        closeDatabase(pInfo);
        if (result == dlpErrNotFound) {
            debug_print("(successfully reached end of records ...)\n");
            return leaveGetRecord(pInfo, AGCLIENT_IDLE);
        }
        else {
            *errCode = AGCLIENT_UNKNOWN_ERR;
            return leaveGetRecord(pInfo, AGCLIENT_ERR);
        }
    }
    pInfo->record = AGRecordInit(pInfo->record, pInfo->id,
                                 AGPalmPilotAttribsToMALMod((uint8)att),
                                 size, pInfo->pilot_buffer, 0, NULL);

    *record = pInfo->record;
    return AGCLIENT_CONTINUE;
}
/*----------------------------------------------------------------------------*/
static int32 getNextModifiedRecord(void * out, AGRecord ** record,
                                    int32 *errCode)
{
    debug_print("GetNextModifiedRecord()\n");

    return getRecordBase((PalmSyncInfo *)out, TRUE, record, errCode);
}
/*----------------------------------------------------------------------------*/
static int32 getNextRecord(void * out, AGRecord ** record, int32 *errCode)
{
    debug_print("GetNextRecord()\n");

    return getRecordBase((PalmSyncInfo *)out, FALSE, record, errCode);
}
/*----------------------------------------------------------------------------*/
static AGBool doClientProcessorLoop(PalmSyncInfo * pInfo, AGNetCtx *ctx)
{
    int32 dummyError;
    int32 cpResult;
    int32 syncCount;
    int32 i, n;
    AGBool cancelled = FALSE;
    AGLocationConfig *lc = NULL;
    int migrate = 0;

    debug_print("doClientProcessorLoop()\n");

    n = AGUserConfigCount(pInfo->userConfig);

    /* Lets check for 3.1 to 3.x migration here */
    if (n == 1) {
        AGServerConfig * sc =
            AGUserConfigGetServerByIndex(pInfo->userConfig, 0);

        /* Yup, no server name */
        if (!sc->serverName) {
            /* Lets look for the 3.1 config database */
            long result;
            int userConfigDBHandle = 0;
            result = dlp_OpenDB(sd, DEFAULT_CARD_NUM,
                                dlpOpenRead|dlpOpenWrite,
                                DEVICE_USERCONFIG_DB_NAME,
                                &userConfigDBHandle);
            if (result > 0) {
                char response[2];
                printf("It looks like you recently upgraded your client"
                       ". Would you\nlike to migrate your old settings"
                       "?[y/n] ");
                if ((fgets(response, 2, stdin) != 0)
                    && ((response[0] == 'y') || (response[0] == 'Y'))) {

                    threeone = 1;
                    /* Retrieve device's idea of current userConfig. */
                    result = readDeviceUserConfig(userConfigDBHandle,
                                                  &pInfo->userConfig,
                                                  threeone);

                    /* This will cause us to write out the 3.1 data
                     as 3.2 when we finish syncing */
                    threeone = 0;

                    /* Done with database for now, so close it. */
                    dlp_CloseDB(sd, userConfigDBHandle);


                    n = AGUserConfigCount(pInfo->userConfig);

                    /* set a flag to delete the old database */
                    migrate = 1;

                }
            }
        }
    }

    for (i = 0; i < n; ++i) {

        AGServerConfig * sc =
            AGUserConfigGetServerByIndex(pInfo->userConfig, i);

        if (cancelled)
            continue;

        if (NULL == sc)
            continue;

        if (sc->disabled)
            continue;

        if (NULL == sc->serverName || sc->serverPort <= 0)
            continue;

        syncCount = 0;
        doStartServer(pInfo, sc, &dummyError);

        do {
            AGCommandProcessorStart(pInfo->commandProcessor);

            pInfo->deviceInfo = AGDeviceInfoNew();
            /* If this fails, we're totally dead.  Exit with fail code. */
            if(!pInfo->deviceInfo)
                return FALSE;

            readDeviceInfo(pInfo);

            if (httpProxy && httpProxyPort) {
                lc = AGLocationConfigNew();
                lc->HTTPUseProxy = 1;
                lc->HTTPName = httpProxy;
                lc->HTTPPort = httpProxyPort;
            jp_logf(JP_LOG_DEBUG,"Using Proxy Server: Address %s: Port %d\n",
                                httpProxy,
                                httpProxyPort);
            }
            if (proxyUsername && proxyPassword) {
                lc->HTTPUseAuthentication = 1;
                lc->HTTPUsername = proxyUsername;
                lc->HTTPPassword = proxyPassword;
            }

          jp_logf(JP_LOG_DEBUG,"Connecting to %s: %s\n", sc->friendlyName, sc->serverName);
            if (socksProxy && socksProxyPort) {
                if (!lc)
                    lc = AGLocationConfigNew();
                lc->SOCKSUseProxy = 1;
                lc->SOCKSName = socksProxy;
                lc->SOCKSPort = socksProxyPort;
            jp_logf(JP_LOG_DEBUG,"Using SOCKS proxy: Address %s: Port %d\n",
                                socksProxy,
                                socksProxyPort);
            }

            pInfo->clientProcessor =
                AGClientProcessorNew(pInfo->currentServerConfig,
                                     pInfo->deviceInfo,
                                     lc,
                                     pInfo->platform,
                                     TRUE,
                                     ctx);

            /* If this fails, we're totally dead.  Exit with fail code. */
            if (NULL == pInfo->clientProcessor) {
                AGDeviceInfoFree(pInfo->deviceInfo);
                return FALSE;
            }
            AGClientProcessorSetBufferServerCommands(pInfo->clientProcessor,
                                                     FALSE);

            AGClientProcessorSync(pInfo->clientProcessor);


            cpResult = AGCLIENT_CONTINUE;
            while (AGCLIENT_CONTINUE == cpResult) {
                cpResult = AGClientProcessorProcess(pInfo->clientProcessor);

                if (AGCLIENT_CONTINUE == cpResult && pInfo->quit) {
                    cancelled = TRUE;
                    cpResult = AGCLIENT_IDLE;
                }
                if (dlp_OpenConduit(sd)<0) {
                    fprintf(stderr, "Exiting on cancel, data not retrieved.\n");
                    exit(1);
                }

            }


            if(cpResult == AGCLIENT_ERR) {

                char *msg = AGGetMsg(pInfo->clientProcessor->errStringId);
                if (msg)
                    jp_logf(JP_LOG_FATAL,"%s\n", msg);
                else
                    jp_logf(JP_LOG_FATAL,"Unknown error\n");

            }
            AGClientProcessorFree(pInfo->clientProcessor);
            AGDeviceInfoFree(pInfo->deviceInfo);

        } while (!cancelled
                 && AGCommandProcessorShouldSyncAgain(pInfo->commandProcessor)
                 && syncCount++ < MAX_SYNCS);
        doEndServer(pInfo, &dummyError);

        /* It's possible to cancel in the middle of an open database,
           so if that happened, close it. */
        if (pInfo->pilot_rHandle)
            closeDatabase(pInfo);

        /* If we migrated from 3.1 to 3.2 delete the 3.1 database */
        if (migrate)
            dlp_DeleteDB (sd, DEFAULT_CARD_NUM, DEVICE_USERCONFIG_DB_NAME);

    }

    return TRUE; /* success */
}
/*----------------------------------------------------------------------------*/
void Disconnect(void)
{
    if(sd == 0)
        return;

    dlp_EndOfSync(sd, 0);
    pi_close(sd);
    sd = 0;
}
/*----------------------------------------------------------------------------*/
void Connect(PalmSyncInfo *pi)
{
    struct pi_sockaddr addr;
    int ret;

    if (sd != 0)
        return;

    if ((sd = pilot_connect(device)) < 0) {
        perror("pilot_connect");
        exit(1);
    }

    if( verbose )
        puts("Connected");
}

int malsync (int sd_hack, PalmSyncInfo *pInfo) {
    uint32 pilotID;
    AGNetCtx *ctx;

    sd = sd_hack;

    if ( dlp_OpenConduit(sd) < 0) {
        jp_logf(JP_LOG_FATAL, "Exiting on cancel\n");
        return 1;
    }

    if (!loadSecLib(&ctx)) {
        ctx = (AGNetCtx *)malloc(sizeof(AGNetCtx));
        AGNetInit(ctx);
    }

    if (setupPlatformCalls(pInfo))
        return -1;

    pInfo->userConfig = getUserConfig(&pilotID);
    if (pInfo->userConfig) {
        doClientProcessorLoop (pInfo, ctx);
        storeDeviceUserConfig (pInfo->userConfig, pilotID);
    }
    else {
        jp_logf (JP_LOG_FATAL, "**** ERROR: No SyncMAL user config found!\n");
        jp_logf (JP_LOG_FATAL, "Is AvantGo installed and configured on the PDA?\n");
    }

    if (secnetclose) {
        (*secnetclose)(ctx);
    } else {
        AGNetClose(ctx);
    }

    free(ctx);

    return 0;
}

Generated by  Doxygen 1.6.0   Back to index