syncmanager.cpp

来自「funambol window mobile客户端源代码」· C++ 代码 · 共 1,631 行 · 第 1/5 页

CPP
1,631
字号
/*
 * Funambol is a mobile platform developed by Funambol, Inc. 
 * 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 Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission 
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE 
 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Affero General Public License 
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 * 
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite 
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 * 
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 * 
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably 
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */
#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/AbstractSyncConfig.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>
#include "base/globalsdef.h"

USE_NAMESPACE

static void fillContentTypeInfoList(ArrayList &l, const char*  types);

const char SyncManager::encodedKeyPrefix[] = "funambol-b64-";

// Module variables ----------------------------------------------------------

static char prevSourceName[64];
static char prevSourceUri[64];
static SyncMode prevSyncMode;

static bool isFiredSyncEventBEGIN;
//static bool isFiredSyncEventEND;

// Static functions ------------------------------------------------------------

/**
 * 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;
}

//--------------------------------------------------------------------------

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)
{
    if (!syncItem) { 
        LOG.error("The syncItem is NULL: invalid encoding?");
        return; 
    }

    if (wcschr(syncItem->getKey(), '<') || wcschr(syncItem->getKey(), '&')) {
        char *key= toMultibyte(syncItem->getKey());

        if (!key) {
            LOG.error("encodeItemKey: cannot convert key %" WCHAR_PRINTF, syncItem->getKey());
            return;
        }
        
        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 [] t;
        delete [] key;
    }

}

/*
 * 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(AbstractSyncConfig& 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;
    devInf         = NULL;
    incomingItem   = NULL;
    allItemsList   = NULL;

    syncURL = config.getSyncURL();
    deviceId = config.getDevID();

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

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

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

    if (config.getReadBufferSize() > 0)
        readBufferSize = config.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 (mappings) {
        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;
    }
    if (allItemsList){
#if 0
        while (allItemsList[i]) {
            delete [] allItemsList[i];
            i++;
        }
#endif
        delete [] allItemsList;
        allItemsList = 0;
    }
}

/*
 * 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 count                   = 0;
    const char* requestedAuthType  = NULL;
    ArrayList* list             = NULL; //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;
    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;
    resetError();

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

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

⌨️ 快捷键说明

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