⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 syncmanager.cpp

📁 funambol windows mobile plugin source code, the source code is taken from the funambol site
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/*
 * Copyright (C) 2003-2007 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY, TITLE, NONINFRINGEMENT or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 * 02111-1307  USA
 */
#include "base/fscapi.h"
#include "base/Log.h"
#include "base/debug.h"
#include "base/util/utils.h"
#include "base/base64.h"
#include "base/messages.h"
#include "http/TransportAgentFactory.h"
#include "spds/constants.h"
#include "spds/DataTransformer.h"
#include "spds/DataTransformerFactory.h"
#include "spds/SyncManagerConfig.h"
#include "spds/SyncManager.h"
#include "spds/SyncMLProcessor.h"
#include "spds/spdsutils.h"
#include "syncml/core/TagNames.h"
#include "syncml/core/ObjectDel.h"

#include "event/FireEvent.h"

#include <limits.h>

const char SyncManager::encodedKeyPrefix[] = "funambol-b64-";
char prevSourceName[64];
char prevSourceUri[64];
SyncMode prevSyncMode;

BOOL isFiredSyncEventBEGIN;
BOOL isFiredSyncEventEND;
void SyncManager::decodeItemKey(SyncItem *syncItem)
{
    char *key;

    if (syncItem &&
        (key = toMultibyte(syncItem->getKey())) != NULL &&
        !strncmp(key, encodedKeyPrefix, strlen(encodedKeyPrefix))) {
        int len;
        char *decoded = (char *)b64_decode(len, key + strlen(encodedKeyPrefix));
        LOG.debug("replacing encoded key '%s' with unsafe key '%s'", key, decoded);
        WCHAR* t = toWideChar(decoded);
        syncItem->setKey(t);
        delete [] decoded;
        delete [] key;
        delete [] t;
    }
}

void SyncManager::encodeItemKey(SyncItem *syncItem)
{
    char *key;

    if (syncItem &&
        (key = toMultibyte(syncItem->getKey())) != NULL &&
        (strchr(key, '<') || strchr(key, '&'))) {
        StringBuffer encoded;
        b64_encode(encoded, key, strlen(key));
        StringBuffer newkey(encodedKeyPrefix);
        newkey += encoded;
        LOG.debug("replacing unsafe key '%s' with encoded key '%s'", key, newkey.c_str());
        WCHAR* t = toWideChar(newkey.c_str());
        syncItem->setKey(t);
        delete [] key;
        delete [] t;
    }
}

/**
 * Is the given status code an error status code? Error codes are the ones
 * outside the range 200-299.
 *
 * @param status the status code to check
 */
inline static bool isErrorStatus(int status) {
    return (status) && ((status < 200) || (status > 299));
}

/**
 * Return true if the status code is authentication failed
 *
 * @param status the status code to check
 */
inline static bool isAuthFailed(int status) {
    return (status) && ((status == 401) || (status == 407));
}

/**
 * Return true if there's no more work to do
 * (if no source has a correct status)
 */
bool SyncManager::isToExit() {
    for (int i = 0; i < sourcesNumber; i++) {
        if (sources[i]->getReport()->checkState() == true) {
            return false;
        }
    }
    return true;
}

/*
 * Utility to set a SyncSource state + errorCode + errorMsg.
 */
void SyncManager::setSourceStateAndError(unsigned int index, SourceState  state,
                                         unsigned int code,  const char*  msg) {

    SyncSourceReport* report = sources[index]->getReport();

    report->setState(state);
    report->setLastErrorCode(code);
    report->setLastErrorMsg(msg);
}


// Used to reserve some more space (DATA_SIZE_TOLERANCE) for incoming items.
// This is used to add a little tolerance to the data size of items sent by
// server in case of large object (item splitted in multiple chunks).
long SyncManager::getToleranceDataSize(long size) {
    return (long)(size*DATA_SIZE_TOLERANCE + 0.5);
}


// Used to verify if data size of incoming item is different from the one declared.
bool SyncManager::testIfDataSizeMismatch(long allocatedSize, long receivedSize) {
    long declaredSize = (long) (allocatedSize/DATA_SIZE_TOLERANCE + 0.5);
    if (declaredSize != receivedSize) {
        LOG.info("WARNING! Item size mismatch: real size = %d, declared size = %d", receivedSize, declaredSize);
        return true;
    }
    return false;
}


SyncManager::SyncManager(SyncManagerConfig& c, SyncReport& report) : config(c), syncReport(report) {
    initialize();
}

void SyncManager::initialize() {
    // set all values which are checked by the destructor;
    // previously some pointers were only set later, leading to
    // uninitialized memory reads and potential crashes when
    // constructing a SyncManager, but not using it
    transportAgent = NULL;
    mappings       = NULL;
    sources        = NULL;
    currentState   = STATE_START;
    sourcesNumber  = 0;
    count          = 0;
    commands       = NULL;
    devInf         = NULL;
    incomingItem   = NULL;

    AccessConfig& c = config.getAccessConfig();
    DeviceConfig& dc = config.getDeviceConfig();

    syncURL = c.getSyncURL();
    deviceId = dc.getDevID();

    credentialHandler.setUsername           (c.getUsername());
    credentialHandler.setPassword           (c.getPassword());
    credentialHandler.setClientNonce        (c.getClientNonce());
    credentialHandler.setClientAuthType     (c.getClientAuthType());

    credentialHandler.setServerID           (c.getServerID());
    credentialHandler.setServerPWD          (c.getServerPWD());
    credentialHandler.setServerNonce        (c.getServerNonce());
    credentialHandler.setServerAuthType     (c.getServerAuthType());
    credentialHandler.setServerAuthRequired (c.getServerAuthRequired());

    commands = new ArrayList();

    responseTimeout = c.getResponseTimeout();
    if (responseTimeout <= 0) {
        responseTimeout = DEFAULT_MAX_TIMEOUT;
    }
    maxMsgSize   = c.getMaxMsgSize();
    if (maxMsgSize <= 0) {
        maxMsgSize = DEFAULT_MAX_MSG_SIZE;
    }
    maxObjSize   = dc.getMaxObjSize();
    loSupport    = dc.getLoSupport();
    readBufferSize = 5000; // default value

    if (c.getReadBufferSize() > 0)
        readBufferSize = c.getReadBufferSize();

    syncMLBuilder.set(syncURL.c_str(), deviceId.c_str());
    memset(credentialInfo, 0, 1024*sizeof(char));
    sortedSourcesFromServer = NULL;
    prevSourceName[0] = 0;
    prevSourceUri[0] = 0;
    prevSyncMode = SYNC_NONE;
    isFiredSyncEventBEGIN = FALSE;

}

SyncManager::~SyncManager() {
    if (transportAgent) {
        delete transportAgent;
    }
    if (commands) {
        commands->clear(); delete commands; commands = NULL;
    }
    if (mappings) {
        for (int i=0; i<sourcesNumber; i++) {
            deleteArrayList(&mappings[i]);
            delete mappings[i];
        }
        delete [] mappings; mappings = NULL;
    }
    if (sources) {
        // This deletes only SyncSource array
        // We DON'T want to release SyncSource objects here!
        delete [] sources;
    }
    if (devInf) {
        delete devInf;
    }
    if (incomingItem) {
        delete incomingItem;
    }
    if (sortedSourcesFromServer) {
        int i=0;
        while (sortedSourcesFromServer[i]) {
            delete [] sortedSourcesFromServer[i];
            i++;
        }
        delete [] sortedSourcesFromServer;
    }
}

/*
 * Modification to perform the sync of an array of sync sources.
 */

int SyncManager::prepareSync(SyncSource** s) {

    char* initMsg               = NULL;
    const char* respURI         = NULL;
    char* responseMsg           = NULL;
    SyncML*  syncml             = NULL;
    int ret                     = 0;
    int serverRet               = 0;
    int count                   = 0;
    const char* requestedAuthType  = NULL;
    ArrayList* list             = new ArrayList();
    ArrayList* alerts           = new ArrayList();

    // for authentication improvments
    BOOL isServerAuthRequired   = credentialHandler.getServerAuthRequired();
    int clientAuthRetries       = 1;
    int serverAuthRetries       = 1;
    int authStatusCode          = 200;

    BOOL isClientAuthenticated  = FALSE;
    BOOL isServerAuthenticated  = FALSE;
    Chal*   clientChal          = NULL; // The chal of the server to the client
    Chal*   serverChal          = NULL; // The chal of the client to the server
    Status* status              = NULL; // The status from the client to the server
    Cred*   cred                = NULL;
    Alert*  alert               = NULL;
    SyncSource** buf            = NULL;
    StringBuffer* devInfStr     = NULL;
    BOOL putDevInf              = FALSE;
    char devInfHash[16 * 4 +1]; // worst case factor base64 is four
    unsigned long timestamp = (unsigned long)time(NULL);

    lastErrorCode = 0;

    // Fire Sync Begin Event
    fireSyncEvent(NULL, SYNC_BEGIN);

    URL url(config.getAccessConfig().getSyncURL());
    Proxy proxy;
    LOG.info(MSG_SYNC_URL, syncURL.c_str());

    // Copy and validate given
    sourcesNumber = assignSources(s);
    if (lastErrorCode) {
        ret = lastErrorCode;    // set when a source has an invalid config
    }

    if (isToExit()) {
        if (!ret) {
            // error: no source to sync
            ret = lastErrorCode = ERR_NO_SOURCE_TO_SYNC;
            sprintf(lastErrorMsg, ERRMSG_NO_SOURCE_TO_SYNC);
        }

        goto finally;
    }

    // Set proxy username/password if proxy is used.
    if (config.getAccessConfig().getUseProxy()) {
        //char* proxyHost = config.getAccessConfig().getProxyHost();
        //int    proxyPort = config.getAccessConfig().getProxyPort();
        const char* proxyUser = config.getAccessConfig().getProxyUsername();
        const char* proxyPwd  = config.getAccessConfig().getProxyPassword();
        proxy.setProxy(NULL, 0, proxyUser, proxyPwd);
    }

    mappings = new ArrayList*[sourcesNumber + 1];
    for (count = 0; count < sourcesNumber; count++) {
        mappings[count] = new ArrayList();
        LOG.info(MSG_PREPARING_SYNC, _wcc(sources[count]->getName()));
    }

    syncMLBuilder.resetCommandID();
    syncMLBuilder.resetMessageID();
    config.getAccessConfig().setBeginSync(timestamp);

    // Create the device informations.
    devInf = createDeviceInfo();

    // check device information for changes
    if (devInf) {
        char md5[16];
        devInfStr = Formatter::getDevInf(devInf);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -