updater.cpp

来自「funambol window mobile客户端源代码」· C++ 代码 · 共 459 行

CPP
459
字号
/*
 * 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 "Updater.h"
#include "pim/difftime.h"
#include "http/WinTransportAgent.h"
#include "http/URL.h"
#include "http/Proxy.h"
#include "http/TransportAgent.h"
#include "http/TransportAgentFactory.h"
#include "base/errors.h"
#include "localizationUtils.h"
#include "pim/maincpp.h"
#include "HwndFunctions.h"

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


//
// Init static pointer.
//
Updater* Updater::pinstance = NULL;

/*
* Method to get the sole instance
*/
Updater* Updater::getInstance(const char* comp, HWND hwnd, ClientSettings* cs) {
    if (pinstance == NULL) {       
        pinstance = new Updater(comp, hwnd, cs);                
    }
    return pinstance;
}

    // method used to get the singleton instance
Updater* getUpdater(const char* comp, HWND hwnd, ClientSettings* cs){
    return Updater::getInstance(comp, hwnd, cs);
}

Updater::Updater(const char* comp, HWND hwnd, ClientSettings* cs) 
                                    : params(cs->getUpdateParams()) {

    component = comp;
    version   = cs->getDeviceConfig().getOem();
    uiHwnd = hwnd;
    settings  = cs;
    readParams();    
    populateTime();

}

Updater::~Updater() { }

int Updater::storeParams() {
    settings->storeUpdateParams();
    return 0;
}

int Updater::readParams() {
    settings->readUpdateParams();
    return 0;
}

int Updater::populateTime() {
    
    FILETIME ft;
    SYSTEMTIME st, remindst, httpst, beginning;
    int remind = 0, http = 0;
    unsigned long lastCheckUpdate = string2long(params.getLastCheckUpdate().c_str());
    __int64 llTmp;
    
    // the beginning of the count of the timestamp
    beginning.wYear = 1970;
    beginning.wMonth = 1;
    beginning.wDay = 1;
    beginning.wHour = 0;
    beginning.wMinute = 0;
    beginning.wSecond = 0;
    beginning.wMilliseconds = 0;

    GetSystemTime(&st);
        
    string t = params.getIntervalRemind();
    if (t != "") { remind = atoi(t.c_str()); } else { remind = 0; }
     
    t = params.getIntervalCheckUpdateHttp();
    if (t != "") { http = atoi(t.c_str()); } else { http = 0; }
    
    // the offset from the 1970
    remindst = DT_AddDiff(nano100SecInMin, remind, &beginning);
    httpst   = DT_AddDiff(nano100SecInMin, http,   &beginning);
    
    // convert all the times into unsigned long
    SystemTimeToFileTime(&st, &ft);
    memcpy (&llTmp, &ft, sizeof (__int64));
    llTmp = (llTmp - 116444736000000000) / 10000000;    
    currentTime = (unsigned long) llTmp;

    SystemTimeToFileTime(&remindst, &ft);
    memcpy (&llTmp, &ft, sizeof (__int64));
    llTmp = (llTmp - 116444736000000000) / 10000000;
    currentRemindTime = (unsigned long) llTmp;
    currentRemindTime = currentRemindTime + lastCheckUpdate;

    SystemTimeToFileTime(&httpst, &ft);
    memcpy (&llTmp, &ft, sizeof (__int64));
    llTmp = (llTmp - 116444736000000000) / 10000000;    
    currentHttpIntervalTime = (unsigned long) llTmp;
    currentHttpIntervalTime = currentHttpIntervalTime + lastCheckUpdate;
    
    return 0;
}

int Updater::checkUpdateFromServer() {
    requestUpdate();      
    return 0;
}

int Updater::startManually() {    
    // set the lastCheckUpdate in the registry to be saved later
    params.setLastCheckUpdate(long2string(currentTime));  
    storeParams();
    launchUpdateProcess();           
    return 0;
}

/**
* check the update on the server. 
* return  0 if there is no action to do
* return  1 if there is something to download
*/
int Updater::checkIsToUpdate() {
    
    int ret = 1;
        
    if (currentTime < currentRemindTime) {  
        LOG.debug("No time to check on local");
        ret = 0;
        goto finally;
    }

    // after this check the params are filled with the right information
    // If needed, the check is on the server
    if (currentTime > currentHttpIntervalTime) {
        LOG.info("Check on server location for update");        
        requestUpdate();

    }    
    
    // set the lastCheckUpdate in the registry to be saved later
    params.setLastCheckUpdate(long2string(currentTime));
    storeParams();

    if (params.getVersion() == "-1") {       
        LOG.debug("The version update is -1: nothing to do. Never check the update");        
        ret = 0;
    }

finally:
    return ret;
}


int Updater::start() {
    
    // int ret = checkUpdate();
    int ret = showMessage(isMandatory());
    
    if (ret == 0) { // response is yes  
        LOG.info("User chooses to start the update procedure...");
        
        // minimize the window if there is one
        if (uiHwnd == NULL) {
            uiHwnd = HwndFunctions::getWindowHandle();
        }
        if (uiHwnd != NULL) {
            SendMessage(uiHwnd, ID_MYMSG_OK, NULL, NULL);
        }
               
        params.setNow("1");
        launchUpdateProcess();
        // launch the browser process
        // the other stuffs are closed by the uninstall process
        // 
    } else if (ret == 1){
        LOG.info("User chooses update later...");
        // response is Later
        params.setLater("1");
        // goto finally;
    } else if (ret == 2) {
        // response is skip
        // message use the Update Software
        LOG.info("User chooses to skip the update...");
        params.setSkipped(params.getVersion());
        OpenMessageBox(uiHwnd, IDS_BUT_OK, IDS_UP_MESSAGE_SKIPPED);   
               
    }
    storeParams();
   
    return ret;
}

int Updater::startWithoutUI() {    
    int ret = checkIsToUpdate();
    if (ret != 0) {
        start();
    }
    return 0;
}

bool Updater::launchUpdateProcess() {
    
    SHELLEXECUTEINFO lpExecInfo;
    memset(&lpExecInfo, 0, sizeof(SHELLEXECUTEINFO));
    lpExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);    
    wchar_t* site = toWideChar(params.getUrlUpdate().c_str());
    lpExecInfo.lpFile = site;
    lpExecInfo.nShow = SW_SHOWNORMAL;
    lpExecInfo.lpVerb = _T("open");
    ShellExecuteEx(&lpExecInfo);
    if (site) { delete [] site; site = NULL; }
    return true;
}

bool Updater::isMandatory() {
    return (params.getMandatory() != "0") ? true : false;
}


void Updater::updateTime() {
    populateTime();
    params.setLastCheckUpdate(long2string(currentTime));  
    storeParams();
}

int Updater::requestUpdate() {
    
    URL url;
    string s;
    if (params.getUrlCheck().empty() || params.getUrlCheck() == "0") {        
        
        url.setURL(settings->getAccessConfig().getSyncURL());
        string port;
        if (url.port != 0) { port = ":"; port += itow(url.port); }
        
        // compose the url
        s = url.protocol;
        s += "://"; 
        s += url.host;
        s += port;
        s += UP_URL_RESOURCE;        

    } else {
        s = params.getUrlCheck().c_str();        
    }
    
    // add the component and version to the url
    s += "?";
    s += UP_URL_COMPONENT;
    s += component;
    s += "&";
    s += UP_URL_VERSION;
    s += version;

    url.setURL(s.c_str());
    
    Proxy proxy;
    
    TransportAgent* transportAgent = NULL;
    transportAgent = TransportAgentFactory::getTransportAgent(url, proxy);
           
    string message = "";

    char* response = transportAgent->sendMessage(message.c_str());

    if (response != NULL) {
        parseMessage(response);
    } else {        
        LOG.error("Client update: %i: %s", getLastErrorCode(), getLastErrorMsg());        
        LOG.error("Uses the stored parameters");
    } 

    if (params.getMandatory() != "0") {
        params.setMandatory(params.getVersion());
        params.setSkipped("0");
    }

    return 0;
}

string getNewLine(string& s) {
    string newline;
    size_t pos1 = s.find("\n");
    if(pos1 == string::npos){
        LOG.error("Updater: no newlines in message?");
        return newline;
    }
    size_t pos2 = pos1 + 1 ;

    while (s[pos1-1] == '\r'){
        pos1--;
    }
    newline = s.substr(pos1, pos2-pos1);
    return newline;
}

list<string> getListedString(string& s, string separator) {

    list<string> allString;

    allString.clear();
    
    size_t seplen = separator.length();
    char *base = (char*)s.c_str();
    char *p = strstr(base, separator.c_str());

    while (p) {
        string token(base, p - base);
        allString.push_back(token);
        base = p + seplen;
        p = strstr(base, separator.c_str());
    }
    string token(base);
    allString.push_back(token);

    return allString;
}

/*
* return -1: no new lines
*/
int Updater::parseMessage(string message) {
    
    string newline = getNewLine(message);
    if (newline == "") {
        return -1;
    }
    string line;
    list<string> allString = getListedString(message, newline);
    list<string>::iterator it;
     
    for (it = allString.begin(); it != allString.end(); it++) {
        line = *it;
        if (line.find(UP_MANDATORY) == 0) {  
            string mand = line.substr(strlen(UP_MANDATORY));        
            if (mand == "mandatory") {
                params.setMandatory("1");
            } else {
                // if the current update is not mandatory but the previous was, 
                // the parameter is not overwritten
                if (params.getMandatory() == "0") {
                    params.setMandatory("0");
                }
            }
        } else if (line.find(UP_RELEASE_DATE) == 0) {         
            params.setReleaseDate(line.substr(strlen(UP_RELEASE_DATE)));
        } else if (line.find(UP_SIZE) == 0) {         
            params.setSize(line.substr(strlen(UP_SIZE)));
        } else if (line.find(UP_VERSION) == 0) {         
            params.setVersion(line.substr(strlen(UP_VERSION)));
        } else if (line.find(UP_URL_UPDATE) == 0) {         
            params.setUrlUpdate(line.substr(strlen(UP_URL_UPDATE)));
        } else if (line.find(UP_URL_COMMENT) == 0) {         
            params.setUrlComment(line.substr(strlen(UP_URL_COMMENT)));
        }
    }
    
    return 0;
}

int getBuildNumberFromVersion(const char* swv) {
        
    int major=0, minor=0, build=0;
    if (!swv) {
        return 0;
    }    
    sscanf(swv, "%d.%d.%d", &major, &minor, &build);
    return (major*10000 + minor*100 + build);
}

int Updater::showMessage(int type) {
    
    int ret = -1;
    int currentVersion = getBuildNumberFromVersion(params.getCurrentVersion().c_str());
    int version = getBuildNumberFromVersion(params.getVersion().c_str());
    
    if (params.getCurrentVersion() == params.getVersion()) {
        ret = 3;
        LOG.debug("The version required is the same installed on the client");
    } else if (currentVersion > version) {
        ret = 3;
        LOG.debug("The version required is lower than the installed on the client");
    } else if (!isMandatory()) {
        if (params.getVersion() == params.getSkipped()) {
            ret = 4;            
            LOG.debug("The version required is the same just skipped");
        } else {                
            ret = OpenMessageBox(uiHwnd, IDS_BUT_NOW_LATER_SKIP, IDS_UP_MESSAGE);        
            LOG.debug("Asked if the user want update (no mandatory): response (0Ye, 1La, 2Sk) %i", ret);
        }
    } else {
        ret = OpenMessageBox(uiHwnd, IDS_BUT_NOW_LATER, IDS_UP_MESSAGE);        
        LOG.debug("Asked if the user want update (mandatory): response (0Ye, 1La) %i", ret);
    }
    
    return ret;
}


string Updater::long2string(unsigned long v) {
    
    char tt[256];
    sprintf(tt, "%lu", v);
    string s(tt);
    return s;
}

unsigned long Updater::string2long(string v) {
    
   return (unsigned long)atol(v.c_str());

}

⌨️ 快捷键说明

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