startsync.cpp

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

CPP
1,301
字号
/*
 * 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".
 */


// startsync.cpp - main module for the sync application
//

// Windows Header Files:
#include <windows.h>
#include <initguid.h>
#include <Notify.h>
#include <Pmpolicy.h>
#include "pim/mail/MailServer2Client.h"
#include "base/startcmd.h"
#include "base/util/utils.h"
#include "http/WinTransportAgent.h"

#include "pim/SettingFunctions.h"
#include "pim/maincpp.h"
#include "notify/addresschange.h"
#include "pim/difftime.h"
#include "usernotify.h"
#include "base/Log.h"
#include "pushmessage.h"
#include "notify/util.h"
#include "notify/timed_msgbox.h"
#include "spds/constants.h"
#include "OTAConfigMessage.h"
#include "OTAConfigMessageHandler.h"
#include <cemapi.h>
#include "pim/utils.h"
#include <string>
#include <list>
#include "customization.h"
#include "processUtils.h"
using namespace std;

#include "pim/maincpp.h"
//
// USE the pim/ClientSettings.h. THis must be shared with the same ClientSettings of the
// FunambolClient
//
#include "pim/ClientSettings.h"
#include "OutOfMemoryException.h"

#include "HwndFunctions.h"
#include "localizationUtils.h"

#define DIMCONF 128
#define DIM_PATH 256
#define NOT_RETURN_TO_MAIN_FORM -3
#define NO_SOURCES_FROM_TRANSPORT -12

#ifdef WIN32_PLATFORM_WFSP
#include "funresourcesp.h"
#endif
#ifdef WIN32_PLATFORM_PSPC
#include "funresourceppc.h"
#endif


#define PARAM_AVAILABLE         TEXT("available")
#define PARAM_REMOVENOTIF       TEXT("removeNotif")
#define PARAM_SCHEDULE          TEXT("schedule")
#define PARAM_CRADLE            TEXT("cradle")
#define PARAM_REGISTER          TEXT("register")
#define PARAM_DEREGISTER        TEXT("deregister")
#define PARAM_NOTIFY            TEXT("/notify")
#define PARAM_TRANSPORT         TEXT("transport")
#define PARAM_INCLUSIVE         TEXT("inclusive")
#define PARAM_MANUAL            TEXT("manual")
#define PARAM_TCPIP             TEXT("tcpip")
#define PARAM_CLEANUP           TEXT("cleanup")
#define PARAM_REFRESHSERVER     TEXT("refresh-from-server")
#define PARAM_REFRESHCLIENT     TEXT("refresh-from-client")
#define PARAM_T_REFRESHSERVER   TEXT("transport-refresh-from-server")
#define PARAM_T_REFRESHCLIENT   TEXT("transport-refresh-from-client")
#define PARAM_SEND_LOG          TEXT("sendlog")
#define PARAM_REMOVE_SCHEDULE   TEXT("remove-schedule")
#define PARAM_REFRESH_CONFIG    TEXT("refresh-config")
#define PARAM_TWO_WAY_CONFIG    TEXT("two-way-config")



#define QUEUED_SYNC_DELAY       1       // Dalay time (seconds) before starting a queued sync.


//--------------------------------------------------------------------- Prototypes

static inline void Alert(const wchar_t *msg, const wchar_t *title=TEXT("Warning"));

static int getPollingTime();
static bool isServerNotified();
static void setServerNotified(bool val);

//static int polling(const wchar_t **sources);
static int schedule();
static int sync(const wchar_t **sources, const wchar_t **ids);
static int doSync(const char* mode, const wchar_t **sources, const wchar_t **ids);
int checkRefreshFromServer(const wchar_t** sources);

static bool g_debug = false;
static int retValue = 0;

void setValuesInRegistry(const wchar_t* name, const wchar_t* value);
wchar_t** getEnabledSourcesFromConfig();
void setSourceOnReg(wchar_t** sources);

void setProperty(const char* fullContext, const char* propertyName, const char* propertyValue);

//--------------------------------------------------------------- Static Functions

static inline void Alert(const wchar_t *msg, const wchar_t *title)
{
#ifdef DEBUG
  	MessageBox (NULL, msg, title, MB_SETFOREGROUND |MB_OK);
#endif
}

static void trim(wstring& str)
{
  wstring::size_type pos = str.find_last_not_of(' ');
  if(pos != string::npos) {
    str.erase(pos + 1);
    pos = str.find_first_not_of(' ');
    if(pos != string::npos) str.erase(0, pos);
  }
  else str.erase(str.begin(), str.end());
}

/*
* This function save the process id passed by setProcessId or resetProcessId on the registry
* NOT use the function directly but use (re)setProcessID instead
*/
static void writeProcessIdOnRegistry(unsigned long processId) {
    wchar_t pid[128];
    wsprintf(pid, TEXT("%lu"), processId);
    setClientConfiguration(NULL, PROPERTY_SPDM_PID, pid, NULL);
}

static void resetProcessID() {
    writeProcessIdOnRegistry(0);
}

static void setProcessID() {
    DWORD processId = GetCurrentProcessId();
    writeProcessIdOnRegistry(processId);
}


static int getPollingTime()
{

    wchar_t buf[32];

    memset(buf, 0, 32*sizeof(wchar_t));
    getClientConfigurationInternal (TEXT(""), PROPERTY_SPDM_POLLING_NOTIFICATION,
                                 buf, FALSE);
    return wcstol(buf, NULL, 10);

}

static bool isServerNotified()
{
    wchar_t buf[10];

    memset(buf, 0, 10*sizeof(wchar_t));
    getClientConfigurationInternal (TEXT(""), PROPERTY_SPDM_SERVER_NOTIFIED,
                                     buf, FALSE);
    return ( wcscmp(buf, TEXT("1")) == 0);

}

static void setServerNotified(bool val)
{

    setClientConfiguration(
            TEXT(""),
            PROPERTY_SPDM_SERVER_NOTIFIED,
            ( (val) ? TEXT("1") : TEXT("0") ),
            NULL);

}


static void getAppNameForSMS(wchar_t* appName) {

    wchar_t path[256];
    getClientConfigurationInternal (NULL, PROPERTY_SPDM_PATH_INFO, path, NULL);
    wcscpy(appName, path);
    wcscat(appName, TEXT("\\"));
    wcscat(appName, SYNCAPP);    

}

static void getAppName(wchar_t* appName) {

    wchar_t path[256];
    getAppNameForSMS(path);
    wcscpy(appName, TEXT("\""));    
    wcscat(appName, path);
    wcscat(appName, TEXT("\""));


}
/*
* NOT_RETURN_TO_MAIN_FORM: is the value to avoid to send a message for the result page.
* It is globally set.
* the return value is the flag to signal if it is a scheduled sync for client push or 
* a usual scheduled sync.
* @return 0: the usual scheduled sync
* @return 1: the client push signal
*/

static int schedule()
{
    long t = getPollingTime();
    long push = 0;
    long interval = 0;       
    int ret = 0;
    
    ClientSettings* cs = getRegConfig();
    string pushS = cs->getPush();    
    push = atoi(pushS.c_str());

    WCHAR appName[MAX_PATH];
    getAppName(appName);
    SYSTEMTIME lpTime;
    SYSTEMTIME pollTime;

    LOG.debug("Schedule start");
    if (t > 0 || push > 0) {

        LOG.debug("Scheduling '%ls'", appName);

                        
            //
            // Schedule the polling before running the sync.
            // it needs to avoid disable of polling if the user stops the sync.
            //
            // NOTE: for the client push notification, the schedule is set using the
            // parameter clientPushInterval.
            if (push > 0) {
                string cpinterval = cs->getClientPushInterval();
                if (cpinterval == "" || cpinterval.length() > 0) {
                    interval = (cpinterval == "" ? 0 : atol(cpinterval.c_str()));
                    if (interval > 0) {
                        LOG.info("CP: Push schedule");
                        ret = 1;
                    } else {                
                        LOG.info("CP: Push doesn't set to schedule");
                        CeRunAppAtTime(appName, 0);
                        ret = 1; 
                        retValue = NOT_RETURN_TO_MAIN_FORM;
                        return ret;
                    }
                }                
            } else {
                LOG.info("Schedule");
                interval = t;
                ret = 0;
            }
            GetLocalTime(&lpTime);
            pollTime = DT_AddDiff(nano100SecInMin, interval, &lpTime);
            BOOL isSchedul = CeRunAppAtTime(appName,&pollTime);                       

        LOG.info("Next scheduled sync of %S will start at '%02d.%02d.%02d'", 
                 appName, pollTime.wHour, pollTime.wMinute, pollTime.wSecond);

    }
    else if (t == 0 && push == 0) {
        LOG.info("Scheduled removed");                
        CeRunAppAtTime(appName,0);
        resetPIMModifications(NULL);
    }

    LOG.debug("Schedule end");
    retValue = NOT_RETURN_TO_MAIN_FORM;
    return ret;
}

static int notify(const wchar_t **sources=NULL)
{
    int responseCode = notifyAddressChange(TEXT(APPLICATION_URI));

    if (responseCode == AN_AddressAccepted) {
        setServerNotified(true);
    }
    else {
        setServerNotified(false);
    }
    return responseCode;
}

static int sync(const wchar_t **sources = NULL, const wchar_t **ids = NULL)
{
    return doSync(NULL, sources, ids);
}

static int recover(const char* mode, const wchar_t **sources)
{
    return doSync(mode, sources, NULL);
}

//static int inclusive(const wchar_t **sources)
//{
//    doSync(mode, sources, NULL);
//}

/**
 * @param sources - syncronize the specified sources. Default is NULL: it means the sources
 *                to sync are the one set in the registry
 * @param ids - the ids of the mail to be downloaded with a inclusive filter
 *              usually it is NULL. Not null only with the "inclusive" command line
 */
static int doSync(const char* mode, const wchar_t **sources, const wchar_t **ids)
{
    HANDLE hMutex;  //Handle to mutex...

    // check for the storage memory...
    checkStorageMemory(0);

    // Create mutex here
    hMutex = CreateMutex(NULL, TRUE, TEXT("FunSyncInProgress") );

    switch(GetLastError()) {
        case ERROR_SUCCESS:
            LOG.debug("Mutex created.");
            break;
        case ERROR_ALREADY_EXISTS:
            // Save the sources to sync into a queue: sync will start at the end
            // of current sync.
            LOG.info("Another sync in progress, current syncis queued");
            updateQueueList(sources);
            retValue = ERR_ANOTHER_SYNC;
            return retValue;
        default:
            LOG.error("Failed to create mutex");
            return -1;
    }


    wchar_t path[DIM_PATH];
    getClientConfigurationInternal(NULL, PROPERTY_SPDM_PATH_INFO, path, NULL);

    HANDLE handleBubble = CreateThread(NULL, 0, createBubble, NULL, 0, NULL);
    if (handleBubble == 0) {
        LOG.error("CreateThread failed: <0x%08x>\n", GetLastError());
    }
    WaitForSingleObject(handleBubble, 0);

    setProcessID();
    // ----------------------------------------------
    retValue = synchronize(path, sources, ids, mode);
    // ----------------------------------------------


    if (retValue == ERR_HTTP_INFLATE) {
        // Manage the ZLIB inflate error: retry the sync with compression disabled. 
        // Note: the registry key 'enableCompression' is set to "0", so the 
        //       zlib compression will be disabled from now on.
        string context = APPLICATION_URI;
        context += CONTEXT_SPDS_SYNCML;
        context += CONTEXT_CONN;
        setProperty(context.c_str(), PROPERTY_ENABLE_COMPRESSION, "0");

        ClientSettings* cs = getRegConfig();
        cs->getAccessConfig().setCompression(FALSE);

        LOG.info("ZLIB compression disabled, retry the sync...");
        retValue = synchronize(path, sources, ids, mode);
    }


    if (retValue == 0 || retValue < ERR_TRANSPORT_BASE) {
        // If sync ended succesfully or if it's NOT a network error, 
        // we reset the PIMList ONLY for the sources just synced.
    	resetPIMModifications(sources);
    }
    else {
        // In case of network errors, we leave the PIMList like it is now. 
        // So if it was a ClientPush, we will schedule a new sync.
    }


    // Start automatically the queued sync.
    // The 'queueList' value is cleared in registry, but a new sync notification
    // could be received during the sync.
    wchar_t** sList = NULL;
    while (sList = readQueueList()) {

        // If we have to do a queued sync, it's better to include also
        // sources that should be synced due to ClientPush. Merge the lists.
        wchar_t** allList = NULL;
        wchar_t** cpList  = readPIMModifications();
        allList = getCompleteList(sList, cpList);

        LOG.info("Starting a QUEUED sync in %d seconds...", QUEUED_SYNC_DELAY);
        SendMessage(HwndFunctions::getWindowHandle(), ID_MYMSG_STARTSYNC_ENDED, 0, 0);
        Sleep(QUEUED_SYNC_DELAY * 1000);
        retValue = synchronize(path, (const wchar_t**)allList, ids, mode);

⌨️ 快捷键说明

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