diff --git a/bazaar/Updater/Updater.cpp b/bazaar/Updater/Updater.cpp index d24be1862..70c5a10f6 100644 --- a/bazaar/Updater/Updater.cpp +++ b/bazaar/Updater/Updater.cpp @@ -63,7 +63,7 @@ Updater::Updater() // get application name -- either from GetExeTitle() if in normal mode // or from environment if in superuser mode - if(state != InsideUpdater) + if(state != InsideUpdater && state != UninstallSucceeded) appName = GetExeTitle(); else if(environ.Find("UPDATER_APPNAME") >= 0) appName = environ.Get("UPDATER_APPNAME"); @@ -122,6 +122,7 @@ void Updater::FailUpdate() break; case Uninstall: + environ.Add("UPDATER_APPNAME", appName); environ.Add("UPDATER_STATE", "UNINSTALLFAILED"); break; @@ -144,6 +145,7 @@ void Updater::SucceedUpdate() break; case Uninstall: + environ.Add("UPDATER_APPNAME", appName); environ.Add("UPDATER_STATE", "UNINSTALLSUCCEEDED"); break; @@ -159,6 +161,7 @@ void Updater::SucceedUpdate() // main updater proc inside normal mode // prepares environment, copy app in temporary folder // and restarts it in superuser mode +// returns true if app must continue execution, false otherwise bool Updater::START_Updater(String const &operation) { // prepare environment for updating @@ -184,63 +187,86 @@ bool Updater::START_Updater(String const &operation) // in temporary folder String tempName = GetTempFileName(); if(!FileCopy(exePath, tempName)) - return false; + return true; #ifdef PLATFORM_POSIX // for posix, change temp file permission // allowing its execution and executes it as a superuser if(chmod(~tempName, 0755) != 0) - return false; + return true; // note the -k to gksu -- it makes it preserve the environment String params = "-k -u root \"" + tempName + "\""; if(SysStart("gksu", params, environ) == -1) - return false; + return true; #else // for windows, simply execute the file if(SysStart(tempName, "", environ) == -1) - return false; + return true; #endif - return true; + // installer process is spawned correctly + // main app must leave + return false; } // uninstall app -void Updater::START_Uninstall(void) +// returns true if app must continue execution, false otherwise +bool Updater::START_Uninstall(void) { - if(!START_Updater("UNINSTALL")) - Exclamation(t_("Uninstall failed&Press OK to quit")); + if(confirmUninstall && !PromptYesNo(t_("This will remove '") + appName + t_("' application&Continue ?"))) + { + state = UninstallAborted; + return true; + } + if(START_Updater("UNINSTALL")) + { + state = UninstallFailed; + return true; + } + return false; } // install app +// returns true if app must continue execution, false otherwise bool Updater::START_Install(void) { - if(!START_Updater("INSTALL")) - return !PromptYesNo(t_("Install failed&Continue running the application?")); - return true; + if(confirmInstall && !PromptYesNo(t_("Install '") + appName + t_("' application?"))) + { + state = InstallAborted; + return true; + } + if(START_Updater("INSTALL")) + { + state = InstallFailed; + return true; + } + return false; } // update app +// returns true if app must continue execution, false otherwise bool Updater::START_Update(void) { - if(!START_Updater("UPDATE")) - return !PromptYesNo(t_("Update failed&Continue running the application?")); - return true; + if(START_Updater("UPDATE")) + { + state = UpdateFailed; + return true; + } + return false; } // app started, must check for update/install requests +// returns true if app must continue execution, false otherwise bool Updater::DO_NormalRun(void) { // we now check if we just want to uninstall app // it can be done by command line --UNINSTALL option if(CommandLine().GetCount() && CommandLine()[0] == "--UNINSTALL") - { - START_Uninstall(); - return false; - } + return START_Uninstall(); // if app not installed, we shall install it if(!appInstalled) - return !START_Install(); + return START_Install(); // not installing nor uninstalling @@ -271,7 +297,7 @@ bool Updater::DO_NormalRun(void) // updater enabled, start it // if update failed, resume normal run, otherwise exit // as the app will be launched again by updater itself - return !START_Update(); + return START_Update(); } bool Updater::DO_InsideUpdater(void) @@ -415,35 +441,37 @@ void Updater::DO_Update(void) bool Updater::DO_UninstallFailed(void) { - Exclamation("Uninstall failed!&Aborting...."); - return false; + state = UninstallFailed; + return true; } bool Updater::DO_InstallFailed(void) { - return PromptYesNo("Install failed&Do you want to run the app anyways?"); + state = InstallFailed; + return true; } bool Updater::DO_UpdateFailed(void) { - return PromptYesNo("Update failed&Do you want to run the app anyways?"); + state = UpdateFailed; + return true; } bool Updater::DO_UninstallSucceeded(void) { - PromptOK("Uninstall succeeded!"); - return false; + state = UninstallSucceeded; + return true; } bool Updater::DO_InstallSucceeded(void) { - PromptOK("Install succeeded!"); + state = InstallSucceeded; return true; } bool Updater::DO_UpdateSucceeded(void) { - PromptOK("Update succeeded!"); + state = UpdateSucceeded; return true; } @@ -596,6 +624,7 @@ bool Updater::Run() NEVER(); break; } + // dummy return false; } @@ -621,3 +650,46 @@ Updater &Updater::UpdateDisable(void) return *this; } +// default set of prompts for installer result +// just an handy shortcut good for most cases +bool Updater::DefaultPrompts(void) +{ + // fine grained behaviour depending on update state + switch(GetState()) + { + case UninstallFailed: + Exclamation(t_("Uninstall of '") + appName + t_("' failed&Press OK to quit")); + return false; + + case UninstallSucceeded: + PromptOK(t_("Uninstall of '") + appName + t_("' complete&Press OK to quit")); + return false; + + case UninstallAborted: + return false ; + + case InstallFailed: + if(!PromptYesNo(t_("Install of '") + appName + t_("' failed&Run without installing?"))) + return false; + return true; + + case InstallSucceeded: + return true; + + case InstallAborted: + return false; + + case UpdateFailed: + if(!PromptYesNo(t_("Update of '") + appName + t_("' failed&Run anyways?"))) + return false; + return true; + + case UpdateSucceeded: + return true; + + // here we're on normal run, no install/uninstall/update process happened + // we should continue normal execution + default: + return true; + } +} diff --git a/bazaar/Updater/Updater.h b/bazaar/Updater/Updater.h index 489d8d25d..7738d4e04 100644 --- a/bazaar/Updater/Updater.h +++ b/bazaar/Updater/Updater.h @@ -1,171 +1,207 @@ -#ifndef _TimberStarter_Updater_h_ -#define _TimberStarter_Updater_h_ - -#include - -using namespace Upp; - -#define SELFUPDATE_OK 0 -#define SELFUPDATE_NO_NETWORK 1 -#define SELFUPDATE_NO_VERSIONFILE 2 -#define SELFUPDATE_NO_APPFILE 3 -#define SELFUPDATE_NO_PERMISSION 4 - -extern int SELFUPDATE_RESULT; - -#define SELFUPDATE(remoteRoot, appName, currentVersion, maxVersion) \ - SELFUPDATE_RESULT = __SelfUpdate(remoteRoot, appName, currentVersion, maxVersion); \ - if(SELFUPDATE_RESULT == -1) \ - return; - -// UPDATE HELPER USED BY SELFUPDATE MACRO - -// IF APP STARTED NORMALLY : -// stores current command line on a temporary file -// restarts current applcation copying to temporary -// folder and acting as a superuser -// parameters passed to application : -// --UPDATE update command -// exepath complete path of itself -// cmdlinepath path of the command line file -// returns 0 if failed, 1 if success -// IF APP STARTED BY UPDATER (as a superuser): -// fetches the update file in a temporary folder -// overwrite the old executable with the new one -// restarts as a normal user the executable with original command line -// returns 2 if failed, 3 if success -// if failed, adds --UPDATEFAILED as last cmdline parameter -// if success, adds --UPDATEOK as last cmdline parameter -// -// IF APP STARTED WITH --UPDATEFAILED AS LAST PARAMETER -// returns 4 -// -// IF APP STARTED WITH --INSTALLFAILED AS LAST PARAMETER -// returns 5 -// -// IF APP STARTED WITH --UPDATEOK AS LAST PARAMETER -// just return 1 and skip further processing -int __SelfUpdate(String const &remoteRoot, String const &appName, String const ¤tVersion, String const &maxVersion); - - -class Updater -{ - private: - // state of updater engine - typedef enum - { - NormalRun, InsideUpdater, - UninstallFailed, InstallFailed, UpdateFailed, - UninstallSucceeded, InstallSucceeded, UpdateSucceeded - } UpdaterState; - UpdaterState state; - - // requested operation - typedef enum { Install, Update, Uninstall } UpdaterOp; - UpdaterOp updaterOp; - - // setup environment for failing update/install - void FailUpdate(void); - - // setup environment for succeeding update/install - void SucceedUpdate(void); - - // main updater proc inside normal mode - // prepares environment, copy app in temporary folder - // and restarts it in superuser mode - bool START_Updater(String const &operation); - - // operations procedures - void START_Uninstall(void); - void DO_Uninstall(void); - bool START_Install(void); - void DO_Install(void); - bool START_Update(void); - void DO_Update(void); - - // installer/updater subfunctions - bool DO_NormalRun(void); - bool DO_InsideUpdater(void); - bool DO_UninstallFailed(void); - bool DO_InstallFailed(void); - bool DO_UpdateFailed(void); - bool DO_UninstallSucceeded(void); - bool DO_InstallSucceeded(void); - bool DO_UpdateSucceeded(void); - - // gets platform root folder - String GetPlatformRoot(void); - - // restarts app in normal mode after updater mode - typedef enum { RestartOrig, RestartNew, RestartTemp } RestartModes; - void RestartApp(RestartModes restartMode); - - // fetch list of available app versions - VectorFetchVersions(void); - double FetchMaxValidVersion(void); - - // fetch the new app version from web server - // and replaces older one - String appBuffer; - bool FetchApp(double ver = -1); - - // running copy of environment - VectorMapenviron; - - // user name (which launched app in normal mode - String user; - - // user configuration path - String userConfigPath; - - // sistem configuration path (to keep installed version number) - String systemConfigPath; - - // flag stating if app is installed - bool appInstalled; - - // current installed version, if any - double installedVersion; - - // copy of starting command line -- needed to restart app correctly - String commandLine; - - // running application name - String appName; - - // copy of running executable path - // when app was first launched in normal mode - String exePath; - - // user variables - double maxVersion; - String webRoot; - - protected: - - public: - - Updater(); - - Updater &SetMaxVersion(double mv) { maxVersion = mv; return *this; } - Updater &SetWebRoot(String const &wr) { webRoot = wr; return *this; } - - // sets updater to manual mode -- if update is available, asks user - Updater &UpdateManual(void); - - // sets updater to auto -- updates app on launch without asking user - Updater &UpdateAuto(void); - - // disable updater -- app will not update on launch - // re-enable it to restart updating system on next run - Updater &UpdateDisable(void); - - bool IsAppInstalled(void) { return appInstalled; } - double GetInstalledVersion(void) { return installedVersion; } - double GetMaxVersion(void) { return maxVersion; } - String const &GetWebRoot(void) { return webRoot; } - - bool Run(void); -}; - -#endif +#ifndef _TimberStarter_Updater_h_ +#define _TimberStarter_Updater_h_ + +#include + +using namespace Upp; + +#define SELFUPDATE_OK 0 +#define SELFUPDATE_NO_NETWORK 1 +#define SELFUPDATE_NO_VERSIONFILE 2 +#define SELFUPDATE_NO_APPFILE 3 +#define SELFUPDATE_NO_PERMISSION 4 + +extern int SELFUPDATE_RESULT; + +#define SELFUPDATE(remoteRoot, appName, currentVersion, maxVersion) \ + SELFUPDATE_RESULT = __SelfUpdate(remoteRoot, appName, currentVersion, maxVersion); \ + if(SELFUPDATE_RESULT == -1) \ + return; + +// UPDATE HELPER USED BY SELFUPDATE MACRO + +// IF APP STARTED NORMALLY : +// stores current command line on a temporary file +// restarts current applcation copying to temporary +// folder and acting as a superuser +// parameters passed to application : +// --UPDATE update command +// exepath complete path of itself +// cmdlinepath path of the command line file +// returns 0 if failed, 1 if success +// IF APP STARTED BY UPDATER (as a superuser): +// fetches the update file in a temporary folder +// overwrite the old executable with the new one +// restarts as a normal user the executable with original command line +// returns 2 if failed, 3 if success +// if failed, adds --UPDATEFAILED as last cmdline parameter +// if success, adds --UPDATEOK as last cmdline parameter +// +// IF APP STARTED WITH --UPDATEFAILED AS LAST PARAMETER +// returns 4 +// +// IF APP STARTED WITH --INSTALLFAILED AS LAST PARAMETER +// returns 5 +// +// IF APP STARTED WITH --UPDATEOK AS LAST PARAMETER +// just return 1 and skip further processing +int __SelfUpdate(String const &remoteRoot, String const &appName, String const ¤tVersion, String const &maxVersion); + + +class Updater +{ + public: + // state of updater engine + typedef enum + { + // internal states + NormalRun, InsideUpdater, + + // public states + UninstallFailed, InstallFailed, UpdateFailed, + UninstallSucceeded, InstallSucceeded, UpdateSucceeded, + UninstallAborted, InstallAborted + } UpdaterState; + + private: + // state of updater engine + UpdaterState state; + + // requested operation + typedef enum { Install, Update, Uninstall } UpdaterOp; + UpdaterOp updaterOp; + + // setup environment for failing update/install + void FailUpdate(void); + + // setup environment for succeeding update/install + void SucceedUpdate(void); + + // main updater proc inside normal mode + // prepares environment, copy app in temporary folder + // and restarts it in superuser mode + bool START_Updater(String const &operation); + + // operations procedures + bool START_Uninstall(void); + void DO_Uninstall(void); + bool START_Install(void); + void DO_Install(void); + bool START_Update(void); + void DO_Update(void); + + // installer/updater subfunctions + bool DO_NormalRun(void); + bool DO_InsideUpdater(void); + bool DO_UninstallFailed(void); + bool DO_InstallFailed(void); + bool DO_UpdateFailed(void); + bool DO_UninstallSucceeded(void); + bool DO_InstallSucceeded(void); + bool DO_UpdateSucceeded(void); + + // gets platform root folder + String GetPlatformRoot(void); + + // restarts app in normal mode after updater mode + typedef enum { RestartOrig, RestartNew, RestartTemp } RestartModes; + void RestartApp(RestartModes restartMode); + + // fetch list of available app versions + VectorFetchVersions(void); + double FetchMaxValidVersion(void); + + // fetch the new app version from web server + // and replaces older one + String appBuffer; + bool FetchApp(double ver = -1); + + // running copy of environment + VectorMapenviron; + + // user name (which launched app in normal mode + String user; + + // user configuration path + String userConfigPath; + + // sistem configuration path (to keep installed version number) + String systemConfigPath; + + // flag stating if app is installed + bool appInstalled; + + // current installed version, if any + double installedVersion; + + // copy of starting command line -- needed to restart app correctly + String commandLine; + + // running application name + String appName; + + // copy of running executable path + // when app was first launched in normal mode + String exePath; + + // user variables + double maxVersion; + String webRoot; + + // install mode -- manual (true) or auto (false) + bool confirmInstall; + + // uninstall mode -- manual (true) or auto (false) + bool confirmUninstall; + + protected: + + public: + + Updater(); + + Updater &SetMaxVersion(double mv) { maxVersion = mv; return *this; } + Updater &SetWebRoot(String const &wr) { webRoot = wr; return *this; } + + // sets updater to manual mode -- if update is available, asks user + Updater &UpdateManual(void); + + // sets updater to auto -- updates app on launch without asking user + Updater &UpdateAuto(void); + + // disable updater -- app will not update on launch + // re-enable it to restart updating system on next run + Updater &UpdateDisable(void); + + // sets installer to auto mode (don't ask user) + Updater &NoConfirmInstall(void) { confirmInstall = false; return *this; } + + // sets installer to manual mode (ask user) + Updater &ConfirmInstall(void) { confirmInstall = true; return *this; } + + // sets uninstaller to auto mode (don't ask user) + Updater &NoConfirmUninstall(void) { confirmUninstall = false; return *this; } + + // sets uninstaller to manual mode (ask user) + Updater &ConfirmUninstall(void) { confirmUninstall = true; return *this; } + + bool IsAppInstalled(void) { return appInstalled; } + double GetInstalledVersion(void) { return installedVersion; } + double GetMaxVersion(void) { return maxVersion; } + String const &GetWebRoot(void) { return webRoot; } + + // executes updater + // return true if app should continue execution + // return false if app should exit + // BEWARE -- you NEED to test this and leave application if false ! + bool Run(void); + + // get updater result status + UpdaterState GetState(void) { return state; } + + // default set of prompts for installer result + // just an handy shortcut good for most cases + bool DefaultPrompts(void); +}; + +#endif